Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};

Array.prototype.contains = function(element){
    for(var i=0;i<this.length;i++){
        if (this[i] == element){ return true; }
    }
    return false;
};



function documentDotLocation(sLocation) {
      var oBody = document.getElementsByTagName("body")[0];
      var oNewDiv = document.createElement('div');
      oNewDiv.innerHTML = '<a href="' + sLocation +'" id="HiddenClickDiv">_</a>';
      oNewDiv.setAttribute('style' , 'visibility: hidden');

      oBody.appendChild(oNewDiv);

      var oDiv = document.getElementById('HiddenClickDiv');

      // Firefox doesn't seem to support click(), but it does support referrer
      if (oDiv.click) {
            oDiv.click();
      } else {
            document.location = sLocation;
      }
}


//OnMouseOut will be falsely triggered if you're mousing to a child of the element
//that has fired the OnMouseOut.  However, you probably only want the event fired
//if the user is leaving the whole control, not the literal element.  Pass the event
//and the ID of the element containing the event, and this function will return 'true'
//if the mouse has really left the control (and all its children).
function IsNotAChildOf(e, potentialParentID){
    var toElement = (e.relatedTarget) ? e.relatedTarget : e.toElement;
    if (toElement){
        var parent = toElement.parentNode;
        while (parent && parent.nodeName != "BODY" && parent.id != potentialParentID){
            parent = parent.parentNode;
        }
        if (parent && parent.id != potentialParentID){
            return true;
        }
    }
    return false;
}




function GetCarImageSize(sSrc , iWidth , iHeight) {

    aSrcParts = sSrc.split("/");

    if (aSrcParts[1] != "images") {
        return sSrc;
    }

    // We only have new paths for 2009 cars and beyond
    if ( (!parseInt(aSrcParts[2])) || (aSrcParts[2] < 2009) ) {
        return sSrc;
    }
    

    // 500x450: Default size for base cars and accessory overalys
    if ( (iWidth == 500) && (iHeight == 450) ) {
        return sSrc;
    }
    
    // 300x245: Accessories for 300x200 base cars
    if ( (iWidth == 300) && (iHeight == 245) ) {
        aSrcParts[4] = 'configurations';
        aSrcParts[5] = 'accessories';
        var sTmp = aSrcParts[aSrcParts.length - 1];
        aSrcParts[aSrcParts.length - 1] = "300x245";
        aSrcParts[aSrcParts.length] = sTmp;
        var sTmp = aSrcParts[aSrcParts.length - 1];
        sTmp = sTmp.replace(".jpg" , ".png");
        aSrcParts[aSrcParts.length - 1] = sTmp;
        sSrc = aSrcParts.join("/");
        return sSrc;
    }

    // 300x200: Base cars
    if ( (iWidth == 300) && (iHeight == 200) ) {
        aSrcParts[4] = 'configurations';
        aSrcParts[5] = 'base-cars';
        var sTmp = aSrcParts[aSrcParts.length - 1];
        sTmp = sTmp.replace(".png" , ".jpg");
        aSrcParts[aSrcParts.length - 1] = "300x200";
        aSrcParts[aSrcParts.length] = sTmp;
        sSrc = aSrcParts.join("/");
        return sSrc;
    }

   // 140x90: Base cars
    if ( (iWidth == 140) && (iHeight == 90) ) {
        aSrcParts[4] = 'configurations';
        aSrcParts[5] = 'base-cars';
        var sTmp = aSrcParts[aSrcParts.length - 1];
        sTmp = sTmp.replace(".png" , ".jpg");
        aSrcParts[aSrcParts.length - 1] = "140x90";
        aSrcParts[aSrcParts.length] = sTmp;
        sSrc = aSrcParts.join("/");
        return sSrc;
    }

}


function SubSelection(TargetSelector,SelectorName) {
   var SelectedValue = document.getElementById(SelectorName).value;
   var thisSelected;
   clearOption(document.getElementById(SelectorName));
     for (var i=document.getElementById(TargetSelector).selectedIndex; i < document.getElementById(TargetSelector).options.length;i++){
       thisSelected = ( document.getElementById(TargetSelector).options[i].value == SelectedValue ? true : false )
       addOption(document.getElementById(SelectorName), document.getElementById(TargetSelector).options[i].text,document.getElementById(TargetSelector).options[i].value,thisSelected);
    }
}

function clearOption(selectbox){
  for (var i=selectbox.options.length-1; i>=0; i--){
    selectbox.options[i] = null;
  }
  selectbox.selectedIndex = -1;
}

function addOption(selectbox,text,value,selected) {
    var optn = document.createElement("option");
    optn.text = text;
    optn.value = value;
    if(selected == true) {
        optn.selected = true;
    }
    selectbox.options.add(optn);
}

/* ------- Geo Targeting ------ */
// GetUserZip takes a parameter, bUseGeotargeting - This will determine if geotargeting should be done on the user or not if the ZIP code cookie is not present.
function GetUserZip(bUseGeotargeting){
    var customerzip = null;
    
    customerzip = GetCookie("customerzip");
    var iptargeted = GetCookie("iptargeted")
    if (customerzip == "null" || customerzip == null) {
        customerzip = '';
    }


    if ( (customerzip == '') && (!iptargeted) && (bUseGeotargeting) ) {       
        $.ajax({
            url:        "/handlers/tools/shopping/getuserzip.ashx",
            timeout:    10000,
            async:      false,
            complete:   function(XMLHttpRequest, textStatus){
                            if (textStatus == "success"){
                                // Set cookie to indicate that IP address was geotargeted so we don't have to call the service over and over if no ZIP was located.
                                SetCookie("iptargeted", "true");
                                customerzip = XMLHttpRequest.responseText;
                                // Only set cookie if a zip was found                                
                                if ( (customerzip != null) && (customerzip != "null") && (customerzip != "") ) {
                                    SetUserZip(customerzip);
                                }
                            }
                        }
        });
    }
    
    return (customerzip == "null" || customerzip == null) ? "" : customerzip;

}

function SetUserZip(sUserZip) { 
    var oDate = new Date();
    oDate.setDate(oDate.getDate() + 30); //30 day duration                                
    SetCookie("customerzip", sUserZip , oDate); 
}

//*********************************************************************************************************
//Filename	: RulesEngine.js
//Author	: Pankil Patel
//Date/Time	: 05/05/2008
//Version   : 1.0
//Purpose	: This file contains methods to support eConfig 3.0 Build & Price configuration.
//Revisions	: Date          Author          Description
//            05/05/2008    Pankil Patel    Creating skeleton  
//            06/20/2008    Pankil Patel    Finalizing Release v. 1.0
//            06/24/2008    Pankil Patel    Implementing Tony's feedback
//            09/09/2008    Pankil Patel    Bug fix AT # 48463
//            11/20/2008    Pankil Patel    Bug fix AT # 51743
//            01/08/2009    Pankil Patel    Bug fix AT # 52521 - Added GetOptionsByaDisplayGroup to return 
//                                                               Options in a particular sort order set in AW.
//*********************************************************************************************************

function ECConfigurationManager()
{
    ///<summary>
    /// ECConfigurationManager function defines the constructor for this class. 
    /// All public methods will be accessed using this public class.
    ///</summary>
    this.AutoApproveChanges = false;    
}

ECConfigurationManager.prototype.ModelList = new Array();



function ECRulesEngineQueryResult()
{
    /// <summary>
    /// ECRulesEngineQueryResult class contains various conflict arrays. After all Configuration Engine rules
    /// are processed, appropriate conflicts are filled and returned to the caller. The PassedValidation flag 
    /// determines if the validation of rules passed or failed. The caller can then send appropriate errors 
    /// to the user.
    /// <b>Types of conflicts returned:</b>
    /// Model Color Conflicts - Exterior/Interior Color conflicts.
    /// Visually Exclusive Conflicts - Asset z-order conflicts.
    /// Option Rules Conflicts - Option Required, Excluded and Included Options
    /// Option Color Conflicts - Option Color Conflicts with selected Exterior/Interior Color conflicts.
    /// </summary>
    this.currentOption;
    this.RequiredOptions = new Array();
    this.IncludedOptions = new Array();
    this.ExcludedOptions = new Array();
    this.VisuallyExclusiveAssets = new Array();
    this.OptionColorConflicts = new Array();
    this.ModelColorConflicts = new Array();
    this.PassedValidation = false;
}

function ECModelColorConflict()
{
    /// <summary>
    /// Returns Model Color Conflicts. 
    /// </summary>
    this.CurrentlySelectedColorCode = "";
    this.CurrentlySelectedColorType = "";
    this.ConflictingColorCode = "";
    this.ConflictingColorType = "";
    this.ModelId = "";
}

function ECOptionColorConflict()
{
    /// <summary>
    /// Returns Option Color Conflicts.
    /// </summary>
    this.OpCode = "";
    this.ColorCode = "";
    this.ColorType = "";
    this.ModelId = "";
}

function ECVisuallyExclusiveConflict()
{
    /// <summary>
    /// This object contains the visually exclusive conflict list. 
    /// It is populated when two assets with same zOrder are selected.
    /// </summary>
    this.CurrentlySelectedAssetId = "";
    this.CurrentlySelectedOpCode = "";
    this.CurrentlySelectedModelId = "";
    this.ConflictingAssetId = "";
    this.ConflictingOpCode = "";
    this.ConflictingModelId = "";
}

function ECVisibleAssets()
{
    /// <summary>
    /// This object contains the Visible Assets Array containing 
    /// currently selected assets. It is populated by calling 
    /// the AddVisibleAsset method and removes any asset that got deselected
    /// by calling the RemoveVisibleAsset. It is populated when two assets with 
    /// same zOrder are selected.
    /// </summary>
}
ECVisibleAssets.prototype.VisibleAssets = new Array();

function ECVisibleAsset(sModelId, sOpCode, sAssetIdent)
{
    /// <summary>
    /// Individual Visible Asset object containing the ModelId, OpCode and AssetIdent selected by user
    /// </summary>
    this.ModelId = sModelId;
    this.OpCode = sOpCode;
    this.AssetIdent = sAssetIdent;
}

// Error Messages
var errModel1000 = new Error(1000,"Model does not exist");
var errModel1001 = new Error(1001,"ModelList Array empty");
var errModel1002 = new Error(1002,"ModelState string not found in url");
var errModel1003 = new Error(1003,"ModelId is required to process rules");
var errOption2000 = new Error(2000,"Model Option List Empty");
var errOption2001 = new Error(2001,"Option does not exist");
var errOption2002 = new Error(2002,"Unable to obtain Options for passed in DisplayGroup");
var errColor3000 = new Error(3000, "Exterior Color List empty for this model");
var errColor3001 = new Error(3001, "Interior Color List empty for this model");
var errColor3002 = new Error(3002, "Error populating Model Color Conflict");
var errRules4000 = new Error(4000, "Error processing Model Option Rules");
var errRules4001 = new Error(4001, "Error Adding Visible Asset");

//Global Counter
SelectedOrderCounter = 0;

ECConfigurationManager.prototype.ProcessModelColorRules = function(sModelId, sSelExtColor, sSelIntColor)
{
    /// <summary>
    /// Assumption: The model list variable within the ConfigurationEngine class must be
    /// populated with data from one or more unique models. The source of the data
    /// for this variable should be the eConfig serverside "getmodeloptions"
    /// method. The "getmodeloptions" method takes in one or more models and
    /// returns a JSON representation of the model data. This JSON is then used to
    /// populate the model list variable. Eventhough multiple models can be added
    /// to the model list variable, the models must be all be unique (different
    /// model IDs). This means that you CAN NOT configure two models with the same
    /// model ID at the same time. Configuration of multiple models is supported
    /// but only if the model IDs are different.

    /// There is no explicit "select model" method because the main methods
    /// (ProcessModelColorRules and ProcessModelOptionRules) both require the model
    /// ID to be passed in as part of the method call. This model id is what we use
    /// to determine which model in the model list to use. For consistency, we
    /// require you to pass in this value even if you only have one model in the
    /// model list. If you pass us a model id that doesn't exist, we'll return an
    /// exception. See the error messages section for more information on the
    /// exceptions this API can raise. You will need to write code to handle the
    /// exceptions appropriately.
    ///
    /// This method allows the selection of Exterior and Interior Color for passed in Model in the state. 
    /// The following steps shows the state selection process during build and price process
    ///
    /// Step1 ProcessModelColorRules  - This method validates the selected exterior/interior colors are valid for the selected Model.
    ///                                 Also, Option Color Conflicts rules will also be checked incase options are already selected in the state.
    /// Step2 ProcessModelOptionRules - This process is called for verifying model option rules and selecting appropriate options.
    ///                                 Since Option Color Rules need to be validated, the colors are obtained from the state
    ///                                 assuming Step1 is already executed. Incase this method is called directly, default
    ///                                 exterior color(first color in array) and default interior color(first color in array for the selected
    ///                                 exterior color) are selected and Option color rules are processed based on this colors.
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose configuration needs to be validated</param>
    /// <param name="sSelExtColor">Currently selected exterior color</param>
    /// <param name="sSelIntColor">Currently selected interior color</param>
    /// <returns>ECRulesEngineQueryResult object with conflicts/no conflicts and passedValidation flag as true/false.</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    
    var oECRE = new ECRulesEngine();
    try
    {
        return oECRE.ValidateConfiguration(sModelId, sSelExtColor, sSelIntColor, "", false);
    }
    catch(e){ throw e;}
    finally{ oECRE = null;}
}

ECConfigurationManager.prototype.ProcessModelOptionRules = function(sModelId, sSelOpCode, bAutoApproveChanges)
{
    /// <summary> 
    /// Assumption: The model list variable within the ConfigurationEngine class must be
    /// populated with data from one or more unique models. The source of the data
    /// for this variable should be the eConfig serverside "getmodeloptions"
    /// method. The "getmodeloptions" method takes in one or more models and
    /// returns a JSON representation of the model data. This JSON is then used to
    /// populate the model list variable. Eventhough multiple models can be added
    /// to the model list variable, the models must be all be unique (different
    /// model IDs). This means that you CAN NOT configure two models with the same
    /// model ID at the same time. Configuration of multiple models is supported
    /// but only if the model IDs are different.

    /// There is no explicit "select model" method because the main methods
    /// (ProcessModelColorRules and ProcessModelOptionRules) both require the model
    /// ID to be passed in as part of the method call. This model id is what we use
    /// to determine which model in the model list to use. For consistency, we
    /// require you to pass in this value even if you only have one model in the
    /// model list. If you pass us a model id that doesn't exist, we'll return an
    /// exception. See the error messages section for more information on the
    /// exceptions this API can raise. You will need to write code to handle the
    /// exceptions appropriately.
    ///
    /// This method allows the selection of Options in state based on Model Option Rules validation for passed in Model in the state. 
    /// The following steps shows the state selection process during build and price process
    ///
    /// Step1 ProcessModelColorRules  - This method validates the selected exterior/interior colors are valid for the selected Model.
    ///                                 Also, Option Color Conflicts rules will also be checked incase options are already selected in the state.
    /// Step2 ProcessModelOptionRules - This process is called for verifying model option rules and selecting appropriate options.
    ///                                 Since Option Color Rules need to be validated, the colors are obtained from the state
    ///                                 assuming Step1 is already executed. Incase this method is called directly, default
    ///                                 exterior color(first color in array) and default interior color(first color in array for the selected
    ///                                 exterior color) are selected and Option color rules are processed based on this colors.
    /// Imp Note: If bAutoApproveChanges is set to true, if Option Color Conflicts arises, the conflict will be raised to the caller. 
    ///           No Option Color will be selected. 
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose configuration needs to be validated</param>
    /// <param name="sSelExtColor">Currently selected exterior color</param>
    /// <param name="sSelIntColor">Currently selected interior color</param>
    /// <param name="sSelOpCode">Currently selected OpCode</param>
    /// <param name="bAutoApproveChanges">If False, returns conflict object to the caller Else resolves conflicts automatically</param>    
    /// <returns>ECRulesEngineQueryResult object with conflicts/no conflicts and passedValidation flag as true/false.</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    var oECRE = new ECRulesEngine();
    try
    {
        return oECRE.ValidateConfiguration(sModelId, "", "", sSelOpCode, bAutoApproveChanges);
    }
    catch(e){ throw e;}
    finally{ oECRE = null;}
}

ECConfigurationManager.prototype.GetVisuallyExclusiveList = function(sModelId, sOpCode, sAssetIdent)
{
    /// <summary>
    /// This method processes the visually exclusive rules and returns any conflicts
    /// Below are the process steps that need to be followed
    /// 1. An Asset is obtained by the user by calling GetAsset method and passing in the ModelId, OpCode and AssetIdent.
    /// 2. For each Option Asset selected, the GetVisuallyExclusiveList is called. For the first time, the VisibleAsset list
    ///    containing all the selected Visible Assets is empty and no conflicts are returned to the user.
    /// 3. The caller should add the selected asset to the Visible Asset List by calling the AddVisibleAssets() method.
    /// 4. For any subsequent calls, the ZOrder of the selected Asset having same ModelId is compared against the assets 
    ///    contained in the VisibleAssetList. Any resulting conflict will be populated in VisuallyExclusiveOptions array
    ///    of the ECQueryRulesEngineResult. Based on the user selection, AddVisibleAsset and RemoveVisibleAsset should be 
    ///    called to add or remove it from the VisibleAsset List.       
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose configuration needs to be validated</param>
    /// <param name="sOpCode">Currently selected OpCode</param>
    /// <param name="sAssetIdent">Currently selected Asset Ident</param>
    /// <returns>ECRulesEngineQueryResult object with conflicts/no conflicts and passedValidation flag as true/false.</returns>
    /// <exception>None</exception>
    var oECVAS, aVisibleAssets, oSelAsset, oQueryResult, bResult;
    oECM = new ECConfigurationManager();
    oQueryResult = new ECRulesEngineQueryResult();
    oECVAS = new ECVisibleAssets();
    
    aVisibleAssets = oECVAS.VisibleAssets;
    oSelAsset = oECM.GetAsset(sModelId, sOpCode, sAssetIdent);
    if(aVisibleAssets != null)
    {
        for(var i=0; i < aVisibleAssets.length; i++)
        {
            oCurAsset = oECM.GetAsset(aVisibleAssets[i].ModelId, aVisibleAssets[i].OpCode, aVisibleAssets[i].AssetIdent);
            if(oCurAsset.ZOrder == oSelAsset.ZOrder)
            {
                //create visually exclusive conflict
                oECEVC = new ECVisuallyExclusiveConflict();
                oECEVC.CurrentlySelectedAssetId = sAssetIdent;
                oECEVC.CurrentlySelectedOpCode = sOpCode;
                oECEVC.CurrentlySelectedModelId = sModelId;
                oECEVC.ConflictingAssetId = aVisibleAssets[i].AssetIdent;
                oECEVC.ConflictingOpCode = aVisibleAssets[i].OpCode;
                oECEVC.ConflictingModelId = aVisibleAssets[i].ModelId;
                oQueryResult.VisuallyExclusiveAssets.push(oECEVC);
		bResult = false;
                break;
            }
        }
    }
    if(bResult)
    {
	oQueryResult.PassedValidation = true;
    }
    return oQueryResult;
}

ECConfigurationManager.prototype.AddVisibleAsset = function(sModelId, sOpCode, sAssetIdent)
{
    /// <summary>
    /// This method is called to add the currently selected asset to the Visible Asset List.  Keeping track of currently selected
    /// and unselected assets using the VisibleAssetList  by adding/removing it from the asset list ensures valid results
    /// of any visually conflicting assets using the GetVisuallyExclusiveList.
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose configuration needs to be validated</param>
    /// <param name="sOpCode">Currently selected OpCode</param>
    /// <param name="sAssetIdent">Currently selected Asset Ident</param>
    /// <returns>Returns true/false.</returns>
    /// <exception>None</exception>
    var oECVA, oECVAS, bAssetExists, bResult;
    bAssetExists = false;
    bResult = false;
    try
    {
        oECVA = new ECVisibleAsset(sModelId,sOpCode,sAssetIdent);
        oECVAS = new ECVisibleAssets();
        for(var i=0; i < oECVAS.VisibleAssets.length; i++)
        {
            if((oECVAS.VisibleAssets[i].ModelId == sModelId)&&(oECVAS.VisibleAssets[i].OpCode == sOpCode)&&(oECVAS.VisibleAssets[i].AssetIdent == sAssetIdent))
            {
                bAssetExists = true;
                break;
            }            
        }
        if(!bAssetExists)
        {
            oECVAS.VisibleAssets.push(oECVA);            
        }        
        bResult = true;
    }
    catch(e){ throw errRules4001; }
    
    return bResult;
}

ECConfigurationManager.prototype.RemoveVisibleAsset = function(sModelId, sOpCode, sAssetIdent)
{
    /// <summary>
    /// This method is called to remove the currently selected asset from the Visible Asset List. Keeping track of currently selected
    /// and unselected assets using the VisibleAssetList  by adding/removing it from the asset list ensures valid results
    /// of any visually conflicting assets using the GetVisuallyExclusiveList.      
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose configuration needs to be validated</param>
    /// <param name="sOpCode">Currently selected OpCode</param>
    /// <param name="sAssetIdent">Currently selected Asset Ident</param>
    /// <returns>Returns true/false.</returns>
    /// <exception>None</exception>
    var oECVAS, bAssetExists, bResult;
    bAssetExists = false;
    bResult = false;
    try
    {
        oECVAS = new ECVisibleAssets();
        for(var i=0; i < oECVAS.VisibleAssets.length; i++)
        {
            if((oECVAS.VisibleAssets[i].ModelId == sModelId)&&(oECVAS.VisibleAssets[i].OpCode == sOpCode)&&(oECVAS.VisibleAssets[i].AssetIdent == sAssetIdent))
            {
                oECVAS.VisibleAssets.splice(i,1);
                bResult = true;
                break;
            }            
        }
    }
    catch(e){ bResult=false;}
    
    return bResult;
}

ECConfigurationManager.prototype.GetAsset = function(sModelId, sOpCode, sAssetIdent) //TODO: Change case for sOpCode
{
    /// <summary>
    /// This method returns the ECAsset object for the passed in Model, Option and AssetIdent within it.      
    /// </summary>
    /// <param name="sModelId">ModelId of the Model</param>
    /// <param name="sOpCode">OpCode for Option whose AssetList needs to be checked</param>
    /// <param name="sAssetIdent">Asset Ident of Asset</param>
    /// <returns>Returns asset object</returns>
    /// <exception>None</exception>
    var oECM, oModel, aAssets;
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId);
    
    try
    {
        if(oModel != null)
        {
            aOptions = oModel.ModelOptionList;
            if(aOptions != null)
            {
                for(var j=0; j < aOptions.length; j++)
                {
                    if(aOptions[j].OpCode == sOpCode)
                    {
                        aAssets = aOptions[j].OptionAssetList;
                        if(aAssets != null)
                        {
                            for(var i=0; i < aAssets.length; i++)
                            {
                                if(aAssets[i].AssetId = sAssetIdent)
                                {
                                    return aAssets[i];                    
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                throw errOption2000;
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){ throw e;}
    finally{oModel = null;}
}

ECConfigurationManager.prototype.GetModel = function(sModelId)
{
    /// <summary>
    /// This method returns the ECModel object for the passed in ModelId
    /// </summary>
    /// <param name="sModelId">ModelId of the requested Model</param>
    /// <returns>ECModel object</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    var oModel, oECM, aModels;
    
    oECM = new ECConfigurationManager();
    aModels = oECM.ModelList;
    
    try
    {
        if(aModels != null)
        {
            for(var i=0; i < aModels.length;i++)
            {
                if(aModels[i].ModelId == sModelId)
                {
                    oModel = aModels[i];
                }
            }
        }
        else
        {
            throw errModel1001;
        }
    }
    catch(e){ throw e;}
    finally{ aModels = null;}
    
    return oModel;
}

ECConfigurationManager.prototype.GetOption = function(sModelId, sOpCode)
{
    /// <summary>
    /// This method returns the ECOption object for the passed in ModelId and OpCode
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose Option is requested</param>
    /// <param name="sOpCode">OpCode for the requested Option</param>
    /// <returns>ECOption object</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    var oOption, oECM, oModel, aOptions;
    
    oECM = new ECConfigurationManager();            
    oModel = oECM.GetModel(sModelId);
    
    try
    {
        if(oModel != null)
        {
            aOptions = oModel.ModelOptionList;
            if(aOptions != null)
            {
                for(var i=0; i < aOptions.length; i++)
                {
                    if(aOptions[i].OpCode == sOpCode)
                    {
                        oOption = aOptions[i];  
                        break;          
                    }
                }
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){ throw e; }
    finally{ oModel = null; }
    // return the populated option object
    return oOption;
}

ECConfigurationManager.prototype.GetOptions = function(sModelId, aOpCodeList)
{
    /// <summary>
    /// This method returns the ECOption objects for the passed in ModelId and OpCode Array
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose Options are requested</param>
    /// <param name="aOpCodeList">Array of OpCodes for which Options are requested</param>
    /// <returns>Array of ECOption object</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    
    var oECM = new ECConfigurationManager();
    var oModel = oECM.GetModel(sModelId);
    var aOptionList = new Array();
    var counter = 0;
    
    try
    {
        if(oModel != null)
        {
            for(var j=0; j < aOpCodeList.length; j++)
            {
                for(var i=0; i < oModel.ModelOptionList.length; i++)
                {
                    if(oModel.ModelOptionList[i].OpCode == aOpCodeList[j])
                    {
                        aOptionList[counter] = oModel.ModelOptionList[i];
                        counter++; 
                    }
                }
            }  
        }
        else
        {
            throw errModel1000;
        }  
    }
    catch(e){ throw e;}
    finally{ oModel = null;}
    return aOptionList;
}

ECConfigurationManager.prototype.GetOptionsByaDisplayGroup = function(sModelId, sOptionDisplayGroup)
{
    /// <summary>
    /// This method returns the ECOption objects for the passed in ModelId and DisplayGroup
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose Options are requested</param>
    /// <param name="sOptionDisplayGroup">DisplayGroup Code for which Options are requested</param>
    /// <returns>Array of ECOption object</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    var oECM = new ECConfigurationManager();
    var oModel = oECM.GetModel(sModelId);
    var aOptionList = new Array();
    var aOptionUnsortedList = new Array();
    var aOptionListwSortOrder = new Array();
    var counter = 0;
    
    try
    {
        for(var i=0; i < oModel.ModelOptionList.length; i++)
        {
            aDisplayGroups = oModel.ModelOptionList[i].DisplayGroups;
            if(aDisplayGroups != null)
            {
                for(var j=0; j < aDisplayGroups.length; j++)
                {
                    if(aDisplayGroups[j].DisplayGrpCd == sOptionDisplayGroup)
                    {
                        aOptionUnsortedList[counter] = oModel.ModelOptionList[i];
                        aOptionListwSortOrder[counter] = {"OpCode":oModel.ModelOptionList[i].OpCode, "SortOrder": aDisplayGroups[j].OptionSortOrder};
                        
                        counter++; 
                    }
                }                    
            }
        }    
        aOptionListwSortOrder.sort(oECM.SortArray);
        for(var k=0; k < aOptionListwSortOrder.length; k++)
        {
            for(var l=0; l < aOptionUnsortedList.length; l++)
            {
                if(aOptionListwSortOrder[k].OpCode == aOptionUnsortedList[l].OpCode)
                {
                    aOptionList[k] = aOptionUnsortedList[l];
                }
            }
        }
        return aOptionList;
    }
    catch(e)
    {
        throw e;
    }
    finally
    { 
        oModel=null; aOptionListwSortOrder = null; aOptionUnsortedList = null;
    }
}

ECConfigurationManager.prototype.SortArray = function(a,b)
{
    var x = parseInt(a.SortOrder);
    var y = parseInt(b.SortOrder);
    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}

ECConfigurationManager.prototype.GetOptionsByDisplayGroup = function(sModelId, aOptionDisplayGroupList)
{
    /// <summary>
    /// This method returns the ECOption objects for the passed in ModelId and DisplayGroups
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose Options are requested</param>
    /// <param name="aOptionDisplayGroupList">Array of DisplayGroup Code for which Options are requested</param>
    /// <returns>Array of ECOption object</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    
    var oECM = new ECConfigurationManager();
    var oModel = oECM.GetModel(sModelId);
    var aOptionList = new Array();
    var counter = 0;
    
    try
    {
        if(oModel != null)
        {
            for(var k=0; k < aOptionDisplayGroupList.length; k++)
            {
                for(var i=0; i < oModel.ModelOptionList.length; i++)
                {
                    aDisplayGroups = oModel.ModelOptionList[i].DisplayGroups;
                    if(aDisplayGroups != null)
                    {
                        for(var j=0; j < aDisplayGroups.length; j++)
                        {
                            if(aDisplayGroups[j].DisplayGrpCd == aOptionDisplayGroupList[k])
                            {
                                aOptionList[counter] = oModel.ModelOptionList[i];
                                counter++; 
                            }
                        }                    
                    }
                }       
            }    
        }
        else
        {
            throw errModel1000;
        }  
    }
    catch(e){ throw e;}
    finally{ oModel = null;}
    return aOptionList;
}

ECConfigurationManager.prototype.GetModelAssets=function(sModelId, sAssetTypeCode, sAssetViewCode)
{
    /// <summary>
    /// This method returns the ECAsset objects for the passed in ModelId, AssetTypeCode and AssetViewCode
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose Assets are requested</param>
    /// <param name="sAssetTypeCode">Asset Type Code i.e. "IMGOVERLAY"</param>
    /// <param name="sAssetViewCode">Asset View Code i.e. "34FRONT"</param>
    /// <returns>ECAsset objects</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    var oECM, oModel, oAssets, aAssets;
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId);
    aAssets = new Array();
    
    try
    {
        if(oModel != null)
        {
            oAssets = oModel.ModelAssetList;
            for(var j=0; j < oAssets.length; j++)
            {
                if(oAssets[j].AssetTypeCode == sAssetTypeCode)
                { if(oAssets[j].AssetViewCode == sAssetViewCode)
                 {
                    aAssets.push(oAssets[j]);
                 }
                }
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){ throw e; }
    finally{ oModel = null; oAssets = null;}
    
    return aAssets;
}

ECConfigurationManager.prototype.GetModelTexts=function(sModelId, sTextTypeCode)
{
    /// <summary>
    /// This method returns the ECText objects for the passed in ModelId and TextTypeCode
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose Assets are requested</param>
    /// <param name="sTextTypeCode">Text Type Code of the Marketing text</param>
    /// <returns>ECText objects</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    
    var oECM, oModel, oTexts, aTexts;
    
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId);
    aTexts = new Array();
    
    try
    {
        if(oModel != null)
        {
            oTexts = oModel.ModelTextList;
            for(var j=0; j < oTexts.length; j++)
            {
                if(oTexts[j].TextTypeCode == sTextTypeCode)
                { 
                    aTexts.push(oTexts[j]);                
                }
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){ throw e; }
    finally{ oModel = null; oTexts = null; }
    
    return aTexts;
}

ECConfigurationManager.prototype.GetOptionAssets=function(sModelId, sAssetTypeCode, sAssetViewCode)
{
    /// <summary>
    /// This method returns the ECAsset objects for the passed in ModelId, AssetTypeCode and AssetViewCode.
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose Assets are requested</param>
    /// <param name="sAssetTypeCode">Asset Type Code i.e. "IMGOVERLAY"</param>
    /// <param name="sAssetViewCode">Asset View Code i.e. "34FRONT"</param>
    /// <returns>ECAsset objects</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    var oECM, oModel, oOptions, aAssets;
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId);
    aAssets = new Array();
    
    try
    {
        if(oModel != null)
        {
            oOptions = oModel.ModelOptionList;
            if(oOptions != null)
            {
                for(var j=0; j < oOptions.length; j++)
                {
                    oAssets = oOptions[j].OptionAssetList;
                    for(var k=0; k < oAssets.length; k++)
                    {
                        if(oAssets[k].AssetTypeCode == sAssetTypeCode)
                        { 
                            if(oAssets[k].AssetViewCode == sAssetViewCode)
                            {
                                aAssets.push(oAssets[k]);
                            }
                        }
                    }
                }
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){ throw e; }
    finally{ oModel = null; oOptions = null; }
    
    return aAssets;
}

ECConfigurationManager.prototype.GetOptionTexts=function(sModelId, sTextTypeCode)
{
    /// <summary>
    /// This method returns the ECTexts objects for the passed in ModelId and TextTypeCode.
    /// </summary>
    /// <param name="sModelId">ModelId of the Model whose Marketing Texts are requested</param>
    /// <param name="sTextTypeCode">Text Type Code</param>
    /// <returns>ECText objects</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    var oECM, oModel, oOptions, oTexts, aTexts;
    
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId);
    aTexts = new Array();            
    
    try
    {   
        if(oModel != null)
        {
            oOptions = oModel.ModelOptionList;
            if(oOptions != null)
            {
                for(var j=0; j < oOptions.length; j++)
                {
                    oTexts = oOptions[j].OptionTextList;
                    for(var k=0; k < oTexts.length; k++)
                    {
                        if(oTexts[k].TextTypeCode == sTextTypeCode)
                        { 
                            aTexts.push(oTexts[k]);                         
                        }
                    }
                }
            }
            else
            {
                throw errOption2000;
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){ throw e; }
    finally{ oModel = null; oOptions = null; oTexts = null; }
                
    return aTexts;
}
        
ECConfigurationManager.prototype.SetModelState= function(sModelState)
{
    /// <summary>
    /// This method restores the state of the Model by parsing the sModelState string containing state information.
    /// The method makes calls to ProcessModelColorRules and ProcessModelOptionRules with AutoApproveflag set to true.
    /// The correct state is selected and the user can obtain the new state by calling GetModelState method.    
    /// Any Model Color Conflicts or Option Color Conflicts are returned to the user.
    /// </summary>
    /// <param name="sModelState">
    ///  This param contains the state information. It is obtained by calling GetModelState and passing ModelId and type "qs"                            
    /// </param>   
    /// <returns>ECRulesEngineQueryResult</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    
    var sModelId, sExtCol, sHondaCode, sIntCol, aOpCodes, aModelState, oQueryResult;
    aModelState = new Array();
    
    try
    {
	sModelState = unescape(sModelState);
	window.text = sModelState;
        aModelState = sModelState.split("|");
            
        sModelId = aModelState[0].substring(2);
        sExtCol = aModelState[1].substring(3);
        sHondaCode = aModelState[2].substring(3);
        sIntCol = aModelState[3].substring(3);
        aOpCodes = aModelState[4].substring(2).split(",");
        
        var oECM = new ECConfigurationManager();
        oECM.ProcessModelColorRules(sModelId, sExtCol, sIntCol);
        
        for(var i=0; i < aOpCodes.length; i++)
        {
            oQueryResult = oECM.ProcessModelOptionRules(sModelId,aOpCodes[i],true);
        }           
    }
    catch(e){ throw e;}
    finally{ sModelId = null; sExtCol = null; sHondaCode = null; sIntCol = null; aOpCodes = null;}
    
    return oQueryResult;
}      

ECConfigurationManager.prototype.GetStateFromQS = function(sParam)
{
    /// <summary>
    /// This method parses the url to obtain the modelstate querystring param passed in. The result is then
    /// passed to SetModelState method which sets the appropriate state.
    /// 
    /// Note: This method will be used in a multiple page build and price process. The state information is
    /// passed to the next/previous page as querystring param.
    /// </summary>
    /// <param name="sModelState">
    ///  This param contains the state information. It is obtained by calling GetModelState and passing ModelId and type "qs"                            
    /// </param>   
    /// <returns>ECRulesEngineQueryResult</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    
    sParam = sParam.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");  
    var regexS = "[\\?&]"+sParam+"=([^&#]*)";  
    var repString = "?" + sParam;
    var regex = new RegExp( regexS );  
    var results = regex.exec( window.location.href );  
    
    var sModelState = results.toString();
    sModelState = sModelState.replace("?" + sParam + "=", "");
    
    try
    {
        if( results == null )    
        {
            throw errModel1002;
        }
        else
        {
            var oECM = new ECConfigurationManager();
            var oQueryResult = oECM.SetModelState(sModelState);
        }
    }
    catch(e){ throw e;}
    finally{ results = null; sModelState = null;}
    
    return oQueryResult;
}

ECConfigurationManager.prototype.ClearModelState= function(sModelId)
{
    /// <summary>
    /// This method clears the state of the model selected colors and accessories.
    /// </summary>
    /// <param name="sModelId">ModelId for which state will be cleared</param>   
    /// <returns>None</returns>
    /// <exception>If Model is not found in the ModelList, it will throw errModel1000 - Model doesn't exist</exception>
    var oECM, oModel, oSelExtCol, oSelIntCol, aOptions, aOptionColors;
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId)
    
    try
    {
        if(oModel != null)
        {
            oModel.IsSelected = false;
            oSelExtCol = oECM.GetSelectedExteriorColor(sModelId);
            if(oSelExtCol != null)
            {
                oSelExtCol.IsSelected = false;
            }
            oSelIntCol = oECM.GetSelectedInteriorColor(sModelId);
            if(oSelIntCol != null)
            {
                oSelIntCol.IsSelected = false;
            }
            aOptions = oModel.ModelOptionList;
            for(var i=0; i < aOptions.length; i++)
            {
                if(aOptions[i].IsSelected)
                {
                    aOptions[i].IsSelected = false;
                    aOptionColors = aOptions[i].OptionColorList;
                    if(aOptionColors.length > 0)
                    {
                        for(var j=0; j < aOptionColors.length; j++)
                        {
                            if(aOptionColors[j].IsSelected)
                            {
                                aOptionColors[j].IsSelected = false;
                            }                        
                        }                    
                    }
                }
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){ throw e;}
    finally{ oModel = null; }
}

ECConfigurationManager.prototype.GetModelState= function(sModelId, sType)
{
    /// <summary>
    /// This method obtains the current state of the configuration. Based on the return type passed in, the configuration 
    /// is returned in either XML/JSON/QueryString format. 
    /// sType values:- XML: xml, JSON: json, QueryString: qs
    /// </summary>
    /// <param name="sModelId">ModelId of the model whose configuration is obtained.</param>
    /// <returns>Configuration XML/JSON string/State String</returns>
    /// <exception>If no Model is present, returns errModel1000 - "Model doesn't exist" error</exception>
    /// <exception>If Configuration XML is requested and XmlDocument is not loaded, an exception is thrown</exception>
    var configXml,configXmlDoc, oECM, oModel,aOptions;
    var aOptionColors, bOptionColor;
    var fTotalPrice, sColorMfgCode, sProductHondaCode, sColorCode;
    oECM = new ECConfigurationManager();            
    oModel = oECM.GetModel(sModelId);
    
    
    if(sType.toLowerCase() == "xml")
    {
        configXml = "<configured-model model_id=\"\" total_configured_price=\"\" config_title=\"\">";
        configXml += "<color exterior_mfg_color_cd=\"\" interior_color_cd=\"\" product_honda_cd=\"\" />";
        configXml += "<accessories></accessories>";
        configXml += "</configured-model>";

        try
	    {
	        configXmlDoc = new ActiveXObject("MSXML2.DOMDocument"); 
	    }
	    catch(e)
	    {
	        try
	        {
	            configXmlDoc = document.implementation.CreateDocument("","",null);
	        }
	        catch(e){ throw e;}  
	    }
	    if(configXmlDoc != null)
	    {
            configXmlDoc.async = "false";
            configXmlDoc.loadXML(configXml);
        
            var oSelExtColor = oECM.GetSelectedExteriorColor(sModelId);
            var oSelIntColor = oECM.GetSelectedInteriorColor(sModelId);
            
            configXmlDoc.selectSingleNode("configured-model/@model_id").text = sModelId;
            configXmlDoc.selectSingleNode("configured-model/@total_configured_price").text = oModel.TotalPrice;
            if(oSelExtColor != null)
            {
                configXmlDoc.selectSingleNode("configured-model/color/@exterior_mfg_color_cd").text = oSelExtColor.ColorMfgCode;
                configXmlDoc.selectSingleNode("configured-model/color/@product_honda_cd").text = oSelExtColor.ProductHondaCode;
            }
            if(oSelIntColor != null)
            {   
                configXmlDoc.selectSingleNode("configured-model/color/@interior_color_cd").text = oSelIntColor.ColorCode;               
            }
            
            
            aOptions = oModel.ModelOptionList;
           
            oAccessories = configXmlDoc.selectSingleNode("configured-model/accessories");
            for(var i=0; i < aOptions.length; i++)
            {
                if(aOptions[i].IsSelected)
                {
                    if(aOptions[i].OptionColorList.length > 0)
                    {
                        aOptionColors = aOptions[i].OptionColorList;
                        for(var j=0; j < aOptionColors.length; j++)
                        {
                            bOptionColor = false;
                            if(aOptionColors[j].IsSelected)
                            {
                                bOptionColor = true;
                                
                                oNewAcc = configXmlDoc.createElement("accessory");
                                oAccessories.appendChild(oNewAcc);
                        
                                oOpCodeAttribute = configXmlDoc.createAttribute("op_code");
                                oOpCodeAttribute.nodeValue = aOptions[i].OpCode;
                                oNewAcc.setAttributeNode(oOpCodeAttribute);
                                                            
                                oPartNumberAttribute = configXmlDoc.createAttribute("part_number");
                                oPartNumberAttribute.nodeValue = aOptionColors[j].PartNumber;
                                oNewAcc.setAttributeNode(oPartNumberAttribute);
                                                            
                                oOptionColorAttribute = configXmlDoc.createAttribute("option_color_cd");
                                
                                if(aOptionColors[j].ColorType == "E")
                                {
                                    oOptionColorAttribute.nodeValue = aOptionColors[j].ColorMfgCode;
                                }
                                else
                                {
                                    oOptionColorAttribute.nodeValue = aOptionColors[j].ColorCode;                         
                                }
                                oNewAcc.setAttributeNode(oOptionColorAttribute);
                                break;
                            }                        
                        }                                  
                    }
                    
                    if(!bOptionColor)
                    {
                        oNewAcc = configXmlDoc.createElement("accessory");
                        oAccessories.appendChild(oNewAcc);
                        
                        oOpCodeAttribute = configXmlDoc.createAttribute("op_code");
                        oOpCodeAttribute.nodeValue = aOptions[i].OpCode;
                        
                        oNewAcc.setAttributeNode(oOpCodeAttribute);
                    }    
                }
                
            }
            return configXmlDoc.xml;
        }
    }
    else if(sType.toLowerCase() == "json")
    {
       
       var sJsonModel, sJsonExtColor, sJsonIntColor, sJsonOption, sExtColor, sIntColor;
       sJsonModel = "{\"ModelId\":\"MODEL_ID\",\"ExteriorColors\":[{EXTERIOR_COLOR}],\"InteriorColors\":[{INTERIOR_COLOR}],\"ModelOptionList\":[OPTIONS]}";
       sJsonExtColor = "\"ColorMfgCode\":\"COLOR_MFG_CODE\",\"ProductHondaCode\":\"PRODUCTHONDACODE\"";
       sJsonIntColor = "\"ColorCode\":\"COLOR_CODE\"";
       sJsonOption = "{\"OpCode\":\"OPCODE\"}";
       
       sJsonModel = sJsonModel.replace("MODEL_ID", sModelId);
       oExtColor = oECM.GetSelectedExteriorColor(sModelId);
       oIntColor = oECM.GetSelectedInteriorColor(sModelId);
       aSelOptions = oECM.GetCurrentlySelectedOptions(sModelId);
       
       if(oExtColor != null)
       {
            sExtColor = sJsonExtColor;
            
            sExtColor = sExtColor.replace("COLOR_MFG_CODE", oExtColor.ColorMfgCode);
            
            if(oExtColor.ProductHondaCode != null)
            {
                sExtColor = sExtColor.replace("PRODUCTHONDACODE", oExtColor.ProductHondaCode);
            }
            else
            {
                sExtColor = sExtColor.replace("PRODUCTHONDACODE", " ");
            }
           
       }
       if(oIntColor != null)
       {
            sIntColor = sJsonIntColor;
            sIntColor = sIntColor.replace("COLOR_CODE", oIntColor.ColorCode);            
       }
       sOptions = sJsonOption;
       for(var k=0; k < aSelOptions.length; k++)
       {
            sOptions = sOptions.replace("OPCODE",aSelOptions[k].OpCode);
            if(!(k == (aSelOptions.length - 1)))
            {
                sOptions += "," + sJsonOption;
            }
       }
       sOptions.replace("," + sJsonOption, "");
       sJsonModel = sJsonModel.replace("EXTERIOR_COLOR",sExtColor);
       sJsonModel = sJsonModel.replace("INTERIOR_COLOR",sIntColor);
       sJsonModel = sJsonModel.replace("OPTIONS",sOptions);
       
       return sJsonModel;
    }
    else if(sType.toLowerCase() == "qs")
    {
        var sQsState,sOpcodes;
        
        sQsState = "M:MODELID|EC:EXTERIORCOLOR|HC:HONDACODE|IC:INTERIORCOLOR|O:OPTIONS|";
        
        sQsState = sQsState.replace("MODELID", sModelId);
        oExtColor = oECM.GetSelectedExteriorColor(sModelId);
        if(oExtColor != null)
        {
            sQsState = sQsState.replace("EXTERIORCOLOR",oExtColor.ColorMfgCode);
            sQsState = sQsState.replace("HONDACODE",oExtColor.ProductHondaCode);
        }
        else
        {
            sQsState = sQsState.replace("EXTERIORCOLOR","");
            sQsState = sQsState.replace("HONDACODE","");
        }
        oIntColor = oECM.GetSelectedInteriorColor(sModelId);
        if(oIntColor != null)
        {
            sQsState = sQsState.replace("INTERIORCOLOR",oIntColor.ColorCode);
        }
        else
        {
            sQsState = sQsState.replace("INTERIORCOLOR","");
        }
        aSelOptions = oECM.GetCurrentlySelectedOptions(sModelId);
        if(aSelOptions != null)
        {
            sOpcodes = "";
            counter = 0;
            aOptionListwSortOrder = new Array();
            for(var i=0; i < aSelOptions.length; i++)
            {
                //added check for Selected Type - 01/13/2009
                if(aSelOptions[i].SType == "Selected")
                {   
                    aOptionListwSortOrder[counter] = {"OpCode":aSelOptions[i].OpCode, "SortOrder": aSelOptions[i].SelectedOrder};
                    counter +=1;
                }
            }
            
            aOptionListwSortOrder.sort(oECM.SortArray);
            for(var j=0; j < aOptionListwSortOrder.length; j++)
            {
                if(aOptionListwSortOrder[j]!= null)
                {
                    if(!(j == (aOptionListwSortOrder.length - 1)))
                    {
                        sOpcodes += aOptionListwSortOrder[j].OpCode + ",";
                    }
                    else
                    {
                        sOpcodes += aOptionListwSortOrder[j].OpCode;
                    }
                }
            }
            sQsState = sQsState.replace("OPTIONS",sOpcodes);
        }
        return sQsState;        
    }
}

ECConfigurationManager.prototype.RemoveModel=function(sModelId)
{
    /// <summary>
    /// This method removes the passed in Model from the ModelList. 
    /// </summary>
    /// <param name="sModelId">ModelId of Model to be removed</param>
    /// <returns>True/False</returns>
    
    var oECM = new ECConfigurationManager();
    var aModels = oECM.ModelList;
    var returnFlag = false;
    if(aModels != null)
    {
        for(i=0; i< aModels.length; i++)
        {
           if(aModels[i].ModelId == sModelId)
           {
                aModels.splice(i,1);
                returnFlag = true;
                break;
           }               
        }
    }
    return returnFlag;
}
        
ECConfigurationManager.prototype.GetCurrentlySelectedOptions = function(sModelId)
{
    /// <summary>
    /// This method gets the currently selected options for the passed in Model
    /// </summary>
    /// <param name="sModelId">ModelId for which selected options are requested</param>
    /// <returns>Option objects or null if none are selected</returns>
    /// <exception>If no Model is present, returns errModel1000 - "Model doesn't exist" error</exception>
    /// <exception>If no OptionList is present, returns errOption2000 - "Model Options doesn't exist" error</exception>
    
    var oECM, oModel, aOptions, aSelOptions;
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId);
    try
    {
        if(oModel != null)
        {
            aSelOptions = new Array();
            aOptions = oModel.ModelOptionList;
            if(aOptions != null)
            {
                for(var i=0; i < aOptions.length; i++)
                {
                    if(aOptions[i].IsSelected)
                    {
                        aSelOptions.push(aOptions[i]);
                    }
                }
            }
            else
            {
                throw errOption2000;
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){throw e;}
    finally{oModel = null; aOptions = null;}
    
    return aSelOptions;
}

ECConfigurationManager.prototype.GetCurrentlyUnselectedOptions = function(sModelId)
{
    /// <summary>
    /// This method gets the currently unselected options for the passed in Model
    /// </summary>
    /// <param name="sModelId">ModelId for which selected options are requested</param>
    /// <returns>Option objects or null if all are selected</returns>
    /// <exception>If no Model is present, returns errModel1000 - "Model doesn't exist" error</exception>
    /// <exception>If no OptionList is present, returns errOption2000 - "Model Options doesn't exist" error</exception>
    var oECM, oModel, aOptions, aUnselOptions;
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId);
    try
    {
        if(oModel != null)
        {
            aUnselOptions = new Array();
            aOptions = oModel.ModelOptionList;
            if(aOptions != null)
            {
                for(var i=0; i < aOptions.length; i++)
                {
                    if(!aOptions[i].IsSelected)
                    {
                        aUnselOptions.push(aOptions[i]);
                    }
                }
            }
            else
            {
                throw errOption2000;
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){throw e;}
    finally{oModel = null; aOptions = null;}
    
    return aUnselOptions;
}

ECConfigurationManager.prototype.GetSelectedExteriorColor = function(sModelId)
{
    /// <summary>
    /// This method gets the currently selected exterior color for the passed in Model
    /// </summary>
    /// <param name="sModelId">ModelId for which selected exterior color is requested</param>
    /// <returns>Model Exterior ECColor object or null if no exterior color is selected.</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    var oSelExtColor, oECM, oModel, oExtColors;
           
    try
    {
        oECM = new ECConfigurationManager();
        oModel = oECM.GetModel(sModelId);  
    
        if(oModel != null)
        {  
            
            oExtColors = oModel.ExteriorColors;
            for(var eCol=0; eCol < oExtColors.length; eCol++)
            {
                if(oExtColors[eCol].IsSelected)
                {
                    oSelExtColor = oExtColors[eCol];
                    break;
                }
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){ throw e; }
    finally { oModel = null;}
    
    return oSelExtColor;
}

ECConfigurationManager.prototype.GetSelectedInteriorColor = function(sModelId)
{
    /// <summary>
    /// This method gets the currently selected interior color for the passed in Model
    /// </summary>
    /// <param name="sModelId">ModelId for which selected interior color is requested</param>
    /// <returns>Model Interior ECColor object or null if no interior color is selected.</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    
    var oSelIntColor, oModel, oIntColors;
    
    try
    {
        oModel = this.GetModel(sModelId);  
    
        if(oModel != null)
        {  
            oIntColors = oModel.InteriorColors;
            for(iCol=0; iCol < oIntColors.length; iCol++)
            {
                if(oIntColors[iCol].IsSelected)
                {
                    oSelIntColor = oIntColors[iCol];
                    break;
                }
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){ throw e; }
    finally { oModel = null; }
    
    return oSelIntColor;
}

ECConfigurationManager.prototype.GetExteriorColors=function(sModelId)
{
    /// <summary>
    /// This method gets all the exterior colors for the passed in Model
    /// </summary>
    /// <param name="sModelId">ModelId for which exterior colors is requested</param>
    /// <returns>Model Exterior ECColor objects or null if no exterior colors are present.</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
     
    var oECM = new ECConfigurationManager();
    var oModel = oECM.GetModel(sModelId);
    
    try
    {
        if(oModel != null)
        {
            return oModel.ExteriorColors;
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e) { throw e; }
    finally { oModel = null;  }
}

ECConfigurationManager.prototype.GetExteriorColorList=function(sModelId,sIntColCode)
{
    /// <summary>
    /// This method gets all the exterior colors for the passed in interior color
    /// </summary>
    /// <param name="sModelId">ModelId for which exterior colors is requested</param>
    /// <param name="sIntColCode">Interior Color Code</param>
    /// <returns>Model Exterior ECColor objects or null if no exterior colors are present.</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    var oECM, oModel, oExtColors, aExtColors, aIntColors;
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId);
    aExtColors = new Array();
    
    try
    {
        if(oModel != null)
        {
            oExtColors = oModel.ExteriorColors;
            for(var i=0; i < oExtColors.length; i++)
            {
                aIntColors = oModel.ColorComboList[oExtColors[i].ColorMfgCode];
                for(var j=0; j < aIntColors.length; j++)
                {
                    if(aIntColors[j] == sIntColCode)
                    {
                        aExtColors.push(oExtColors[i]);
                    }
                }
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e) { throw e; }
    finally { oModel = null;  oExtColors = null; aIntColors = null; }
    
    return aExtColors;
}

ECConfigurationManager.prototype.GetInteriorColors=function(sModelId)
{
    /// <summary>
    /// This method gets all the interior colors for the passed in ModelId
    /// </summary>
    /// <param name="sModelId">ModelId for which interior colors is requested</param>
    /// <returns>Model Interior ECColor objects or null if no interior colors are present.</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    var oECM = new ECConfigurationManager();
    var oModel = oECM.GetModel(sModelId);
    
    try
    {
        if(oModel != null)
        {
            return oModel.InteriorColors;
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e) { throw e; }
    finally { oModel = null;  }
    
}

ECConfigurationManager.prototype.GetInteriorColorList=function(sModelId,sExtColorCode)
{
    /// <summary>
    /// This method gets all the interior colors for the passed in exterior color and Model
    /// </summary>
    /// <param name="sModelId">ModelId for which interior colors are requested</param>
    /// <param name="sExtColCode">Exterior Color Code</param>
    /// <returns>Model Interior ECColor objects or null if no interior colors are present.</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    
    var oECM, oModel, aIntColors, oExtColors, aIntColorList;
    
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId);
    aIntColors = new Array();
    
    try
    {
        if(oModel != null)
        {
            oExtColors = oModel.ExteriorColors;
            
            for(var k=0; k < oExtColors.length; k++)
            {
                if(oExtColors[k].ColorMfgCode == sExtColorCode)
                {
                    aIntColorList = oModel.ColorComboList[oExtColors[k].ColorMfgCode];
                    
                    for(j=0; j < aIntColorList.length; j++)
                    {
                        var color = oECM.GetColor(oModel, aIntColorList[j], "I");
                        if(color){
                            aIntColors.push(color);
                        }
                    }
                    break;
                }
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){ throw e;}
    finally{  oModel = null; oExtColors = null; aIntColorList = null;}
    
    return aIntColors;
}

ECConfigurationManager.prototype.GetColor=function(oModel, sColCode, sColType)
{
    /// <summary>
    /// This method returns a specific ECColor object based on the passed in color code and type
    /// </summary>
    /// <param name="sModelId">ModelId for which exterior/interior color is requested</param>
    /// <param name="sColCode">Mfg Color code for Exterior Color and Color Code for Interior Color</param>
    /// <returns>Model Exterior or Interior ECColor object or null if no colors match the color code and type passed in.</returns>
    /// <exception>If no Model is present, returns "Model doesn't exist" error</exception>
    
    var oExtColors, oIntColors;
    try
    {
        if(oModel != null)
        {
            if(sColType == "E")
            {
                oExtColors = oModel.ExteriorColors;
                for(var i=0 ; i< oExtColors.length ; i++)
                {
                   if(oExtColors[i].ColorMfgCode == sColCode)
                   {
                        return oExtColors[i];
                   }
                }
            }
            else if(sColType == "I")
            {
                oIntColors = oModel.InteriorColors;
                for(var i=0; i < oIntColors.length; i++)
                {
                   if(oIntColors[i].ColorCode == sColCode)
                   {
                        return oIntColors[i];
                   }
                }
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e) { throw e;}
    finally { oExtColors = null ; oIntColors = null; }    
}

ECConfigurationManager.prototype.AddModels=function(aModels)
{
    /// <summary>
    /// This method adds the passed in models to the ModelList array. 
    /// NOTE: If the Model already exist in the ModelList Array, it replaces the old Model in the 
    ///       ModelList Array with the new one.
    /// </summary>
    /// <param name="aModels">Array of models to be added</param>
    /// <returns>True/False</returns>
    /// <exception></exception>
    var oECM, aModelList, oModel, bAddModels;
    
    oECM = new ECConfigurationManager();
    bAddModels = false;
    
    try
    {
        if(aModels != null)
        {
            for(var i=0; i < aModels.length; i++)
            {   
                if(aModels[i] != null)
                {
                    oModel = oECM.GetModel(aModels[i].ModelId);
                    if(oModel != null)
                    {
                        //If model already exists, remove it from the ModelList
                        oECM.ModelList.pop(oModel);
                        //Add the new model passed in to the ModelList
                        oECM.ModelList.push(aModels[i]);                       
                    }
                    else
                    {
                        oECM.ModelList.push(aModels[i]);
                    }
                    bAddModels = true;
                }
            }
           
        }
    }
    catch(e){ throw e; }
    finally {}
    
    return bAddModels;
}


ECConfigurationManager.prototype.AddModelAssets = function(sModelId, aNewAssets)
{
    /// <summary>
    /// This method compares the Assets in current Model against the new Assets passed 
    /// and adds any new Assets to the ModelAssetList.
    /// </summary>
    /// <param name="sModelId">Model currently in ModelList</param>
    /// <param name="aNewAssets">Assets Array</param>
    /// <returns>N/A</returns>
    /// <exception>If no Model exists, throws errModel1000 - "Model does not exist" error</exception> 
    var bAsset, aAddAssets, aAssets, oECM, oModel;
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId);
    
    try
    {
        if(oModel != null)
        {
            aAssets = oModel.ModelAssetList;
            if(aNewAssets != null)
            {
                if(aAssets != null)
                {
                    oECM.AddAdditionalArrayValues(aAssets, aNewAssets, "AssetIdent");
                }
            }
        }
        else
        {
            throw errModel1000;
        }
    }
    catch(e){ throw e; }
    finally{ aAddAssets = null; aAssets = null;}
}

ECConfigurationManager.prototype.AddModelTexts = function(sModelId, aNewTexts)
{
    /// <summary>
    /// This method compares the Marketing Texts in current Model against the new Texts passed 
    /// and adds any new Marketing Texts to the ModelTextList.
    /// </summary>
    /// <param name="sModelId">Model currently in ModelList</param>
    /// <param name="aNewTexts">Marketing Texts Array</param>
    /// <returns>N/A</returns>
    /// <exception>If no Model exists, throws errModel1000 - "Model does not exist" error</exception> 
    var bText, aAddTexts, aTexts, oECM, oModel;
    oECM = new ECConfigurationManager();
    oModel = oECM.GetModel(sModelId);
    
    try
    {
        if(oModel != null)
        {
            aTexts = oModel.ModelTextList;
            
            if(aNewTexts != null)
            {
                if(aTexts != null)
                {
                    oECM.AddAdditionalArrayValues(aTexts, aNewTexts, "TextIdent");
                }                
            }
        }
        else
        {
            throw errModel1000;
        }        
    }
    catch(e){ throw e; }
    finally{ aAddTexts = null; aNewTexts = null; aTexts = null;}
}

ECConfigurationManager.prototype.AddOptionAssets = function(sModelId, sOpCode, aNewAssets)
{
    /// <summary>
    /// This method compares the Assets in current Model against the new Assets passed 
    /// and adds any new Assets to the ModelAssetList.
    /// </summary>
    /// <param name="sModelId">Model currently in ModelList</param>
    /// <param name="aNewAssets">Assets Array</param>
    /// <returns>N/A</returns>
    /// <exception>If no Model exists, throws errModel1000 - "Model does not exist" error</exception> 
    var bAsset, aAddAssets, aAssets, oECM, oModel, oOption;
    oECM = new ECConfigurationManager();
    oOption = oECM.GetOption(sModelId, sOpCode);
    
    try
    {
        if(oOption != null)
        {
            aAssets = oOption.OptionAssetList;
            if(aNewAssets != null)
            {
                if(aAssets != null)
                {
                    oECM.AddAdditionalArrayValues(aAssets, aNewAssets, "AssetIdent");
                }                
            }
        }
        else
        {
            throw errModel2001;
        }
    }
    catch(e){ throw e; }
    finally{ aAddAssets = null; aAssets = null;}
}

ECConfigurationManager.prototype.AddOptionTexts = function(sModelId, sOpCode, aNewTexts)
{
    /// <summary>
    /// This method compares the Marketing Texts in current Option against the new Texts passed 
    /// and adds any new Marketing Texts to the OptionTextList.
    /// </summary>
    /// <param name="sModelId">Model currently in ModelList</param>
    /// <param name="sOpCode">Opcode whose text are added</param>
    /// <param name="aNewTexts">Marketing Texts Array</param>
    /// <returns>N/A</returns>
    /// <exception>If no option exists, throws errModel2001 - "Option does not exist"</exception> 
    var bText, aAddTexts, aTexts, oECM, oOption;
    oECM = new ECConfigurationManager();
    oOption = oECM.GetOption(sModelId,sOpCode);
    
    try
    {
        if(oOption != null)
        {
            aTexts = oOption.OptionTextList;
            
            if(aNewTexts != null)
            {
                if(aTexts != null)
                {
                    oECM.AddAdditionalArrayValues(aTexts, aNewTexts, "TextIdent");
                }                
            }
        }
        else
        {
            throw errModel2001;
        }        
    }
    catch(e){ throw e; }
    finally{ aAddTexts = null; aNewTexts = null; aTexts = null;}
}

ECConfigurationManager.prototype.AddAdditionalArrayValues = function(aCurList, aNewList, sIdent)
{
    /// <summary>
    /// This is a helper method that compares two arrays and adds the new items to the current array list.
    /// </summary>
    /// <param name="aCurList">Currently existing Array List</param>
    /// <param name="aNewList">New Array List</param>
    /// <param name="sIdent">Unique identifier to compare the two arrays</param>
    /// <returns>N/A</returns>
    /// <exception>None</exception> 
    var aAddNewValues, bFlag;
    aAddNewValues = new Array();
    
    try
    {
        for(var i=0; i < aNewList.length; i++)
        {
            bFlag = false;
            for(var j=0; j < aCurList.length; j++)
            {
                if(aNewList[i].sIdent == aCurList.sIdent)
                {
                    bFlag = true;
                    break;
                }
            }
            if(!bFlag)
            {
               aAddNewValues.push(aNewList[i]); 
            }
        }
        
        if(aAddNewValues.length > 0)
        {
            for(var k=0; k < aAddNewValues.length; k++)
            {
                aCurList.push(aAddNewValues[k]);
            }
        }
    }
    catch(e){ throw e;}
    finally{ aAddNewValues = null;}
}

ECConfigurationManager.prototype.GetTotalSelectedOptionsPrice = function(sModelId)
{
    /// <summary>
    /// This method calculates the total price of all selected options
    /// </summary>
    /// <param name="sModelId">Unique model identifier</param>
    /// <returns>N/A</returns>
    /// <exception>None</exception> 
     var aSelOptions, fTotalOptionsPrice, oECM;
     oECM = new ECConfigurationManager();

     aSelOptions = oECM.GetCurrentlySelectedOptions(sModelId);
     
     if(aSelOptions != null)
     {
	    if(aSelOptions.length > 0)
	    {
		    fTotalOptionsPrice = 0;
		    for(var i=0; i < aSelOptions.length; i++)
		    {
			    if(aSelOptions[i].OptionType == "Required")
			    {
				    fTotalOptionsPrice += parseFloat(aSelOptions[i].OptionPrice);
			    }
		    }
	    }
     }
     return fTotalOptionsPrice;
}

ECConfigurationManager.prototype.GetTotalSelectedDealerOptionsPrice = function(sModelId)
{
    /// <summary>
    /// This method calculates the total dealer price of all selected options
    /// </summary>
    /// <param name="sModelId">Unique model identifier</param>
    /// <returns>N/A</returns>
    /// <exception>None</exception> 
     var aSelOptions, fTotalOptionsPrice, oECM;
     oECM = new ECConfigurationManager();

     aSelOptions = oECM.GetCurrentlySelectedOptions(sModelId);
     
     if(aSelOptions != null)
     {
	    if(aSelOptions.length > 0)
	    {
		    fTotalOptionsPrice = 0;
		    for(var i=0; i < aSelOptions.length; i++)
		    {
			    if(aSelOptions[i].OptionType == "Required")
			    {
				    fTotalOptionsPrice += parseFloat(aSelOptions[i].DealerOptionPrice);
			    }
		    }
	    }
     }
     return fTotalOptionsPrice;
}
/************************************* Private ECRulesEngine Class **************************************************/
function ECRulesEngine()
{
    this.ValidateConfiguration = function(sModelId, sExtColSel, sIntColSel, sOpCodeSel, bAutoApproveChanges)
    {
        /// <summary>
        /// This method contains the logic for validating a configuration for Model color and option rules. 
        /// 
        /// The sOpCodeSel is optional and is needed when verifying Options selected in the configuration.
        /// The Validation Rules will be processed as follows
        /// 1. If Exterior Color is not passed in, the state is checked to see if the color is already selected.
        ///    If no color is selected, first exterior color in the array will be selected as default. If
        ///    exteriorcolors array is empty, exception errColor3000 is thrown. If wrong exterior color is passed,
        ///    ModelColorConflict is created for that color.
        /// 2. If Interior Color is not passed in, the state is checked to see if the color is already selected.
        ///    If no color is selected, first interior color in the array for the selected exterior color will be 
        ///    selected as default. If interiorcolors array is empty, exception errColor3001 is thrown. If wrong 
        ///    interior color is passed, ModelColorConflict is created for that color.
        /// 3. If both Exterior/Interior Color are passed, Exterior/Interior color combination is verified and any conflicts are
        ///    returned as Model Color Conflicts.
        /// 4. If OpCode is passed in, Process Model Option Rules method is called which processes the Exclude, Required, Include and 
        ///    package rules. It also processes the Option Color Conflict rules for the selected color.
        /// 5. If OpCode is not passed in, Process Option Color Conflict method is called to make sure previously selected accessories
        ///    doesn't conflict with currently passed in colors.
        /// </summary>
        /// <param name="sModelId">ModelId of Model on which configuration Rules are executed</param>
        /// <param name="sExtColSel">Exterior Color of passed in Model</param>
        /// <param name="sIntColSel">Interior Color of passed in Model</param>
        /// <param name="sOpCodeSel">OpCode for which rules are validated</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If not, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <returns>ECRulesEngineQueryResult object with passedValidation flag and any conflicts</returns>
        /// <exception>If ModelId is not passed, throws "No ModelId Passed".</exception> 
        /// <exception>If ModelId passed is not in ConfigurationEngine, throws "Passed in Model not in Configuration".</exception> 
        try
        {
            if(sModelId != null)
            {
                var oECM = new ECConfigurationManager();
                var oQueryResult = new ECRulesEngineQueryResult();
                var oModel = oECM.GetModel(sModelId);
                var bExtColor = false;
                var bIntColor = false;
                var bValidExtIntColor = false;
                var oExtColSel, oIntColSel, oCurExtColSel, oCurIntColSel, aIntColors;
                
                if(oModel != null)
                {
                    //Check if Exterior Color Exists
                    if(sExtColSel == null || sExtColSel == "") 
                    {
                        oCurExtColSel = oECM.GetSelectedExteriorColor(sModelId);
                        if(oCurExtColSel != null)
                        {
                            sExtColSel = oCurExtColSel.ColorMfgCode;
                        }
                        else
                        {
                            if(oModel.ExteriorColors.length > 0)
                            {
                                //Selecting default color in the list
                                sExtColSel = oModel.ExteriorColors[0].ColorMfgCode; 
                                oModel.ExteriorColors[0].IsSelected = true;   //TODO: ADD 
                            }
                            else
                            {
                                // No Exterior colors for this model
                                throw errColor3000; 
                            }                           
                        }
                    }
                    else if(sExtColSel == "None")
                    {
                        oCurExtColSel = oECM.GetSelectedExteriorColor(sModelId);
                        if(oCurExtColSel != null)
                        {
                            oCurExtColSel.IsSelected = false;
                        }
                    }
                    //else
                    //{
                        //check if the Exterior color is valid
                        oExtColSel = oECM.GetColor(oModel,sExtColSel,"E");
                        if(oExtColSel != null)
                        {
                            bExtColor = true;
                            oCurExtColSel = oECM.GetSelectedExteriorColor(sModelId);
                            if(oCurExtColSel != null)
                            {
                                oCurExtColSel.IsSelected = false;
                            }
                            oExtColSel.IsSelected = true;
                        }
                        else
                        {
                            this.PopulateModelColorConflict(oModel,oQueryResult,sExtColSel,"E", "None","E");
                        }
                    //}
                    
                    //Check if Interior Color Exists
                    if(sIntColSel == null || sIntColSel == "") 
                    {
                        oCurIntColSel =  oECM.GetSelectedInteriorColor(sModelId);
                        if(oCurIntColSel != null)
                        {
                            sIntColSel = oCurIntColSel.ColorCode;
                        }
                        else
                        {
                            if(oModel.InteriorColors.length > 0)
                            {
                                aIntColors = oECM.GetInteriorColorList(sModelId,sExtColSel);
                                sIntColSel = aIntColors[0].ColorCode;
                                aIntColors[0].IsSelected = true;   //TODO: ADD
                            }
                            else
                            {
                                throw errColor3001; // No Interior colors for this model
                            }                            
                        }
                    }
                    else if(sIntColSel == "None")
                    {
                        //If Color passed is "None" then the state of the colors is cleared
                        oCurIntColSel = oECM.GetSelectedInteriorColor(sModelId);
                        if(oCurIntColSel != null)
                        {
                            oCurIntColSel.IsSelected = false;
                        }
                    }
                    //else
                    //{
                        //check if the Interior color is valid for this Model
                        oIntColSel = oECM.GetColor(oModel,sIntColSel,"I");
                        if(oIntColSel != null)
                        {
                            bIntColor = true;
                            oCurIntColSel = oECM.GetSelectedInteriorColor(sModelId);
                            if(oCurIntColSel != null)
                            {
                                oCurIntColSel.IsSelected = false;
                            }
                            oIntColSel.IsSelected = true;
                        }
                        else
                        {
                            this.PopulateModelColorConflict(oModel,oQueryResult,sIntColSel,"I", "None","I");
                        }
                    //}
                    
                    if(bExtColor && bIntColor)
                    {
                        //Validate if the Ext/Int Color Combination is valid or not
                        var aIntColors = oModel.ColorComboList[sExtColSel];
                        
                        for(var j=0; j < aIntColors.length; j++)
                        {
                            if(aIntColors[j] == oIntColSel.ColorCode)
                            {
                                bValidExtIntColor = true;
                                oExtColSel.IsSelected = true;
                                oIntColSel.IsSelected = true;
                                break;
                            }                                    
                        }
                        
                        if(!bValidExtIntColor)
                        {
                            oIntColSel.IsSelected = false;
                            this.PopulateModelColorConflict(oModel,oQueryResult, oExtColSel.ColorMfgCode, oExtColSel.ColorType, oIntColSel.ColorCode, oIntColSel.ColorType);                                
                        }
                    }
                    
                    if(!(sOpCodeSel == null || sOpCodeSel == ""))
                    {
                        this.ProcessModelOptionRules(sModelId, oQueryResult, sOpCodeSel, bAutoApproveChanges);
                    }
                    else
                    {
                        var aOptions = oModel.ModelOptionList;
                        if(aOptions != null)
                        {
                            for(var z=0; z < aOptions.length; z++)
                            {
                                if(aOptions[z].IsSelected)
                                {
                                    this.ProcessOptionColorRules(sModelId, aOptions[z], oECM, oQueryResult, bAutoApproveChanges);
                                }
                            }
                        }
                    }
                    //Calculate the Price
                    this.CalculatePrice(sModelId,oECM);

		    //Update Passed Validation flag
		    this.UpdateValidationStatus(oQueryResult);
                }
                else
                {
                    throw errModel1001;
                }
            }
            else
            {
                throw errModel1003;
            }
        }
        catch(e){throw e;}
        finally
        {
            oModel = null; oExtColSel = null; oIntColSel = null; oCurExtColSel = null; oCurIntColSel = null; aIntColors = null;
        }
        return oQueryResult;
    }
    
    this.UpdateValidationStatus = function(oQueryResult)
    {
	    if(oQueryResult.RequiredOptions.length > 0 || oQueryResult.IncludedOptions.length > 0 || oQueryResult.ExcludedOptions.length > 0 || oQueryResult.OptionColorConflicts.length > 0 || oQueryResult.ModelColorConflicts.length > 0)
        {
		    oQueryResult.PassedValidation = false;
	    }
	    else
	    {
		    oQueryResult.PassedValidation = true;
	    }
    }

    this.PopulateModelColorConflict = function(oModel,oQueryResult,curSelColCode, curSelColType, conColCode, conColType)      
    {
        /// <summary>
        /// This is a helper method that populates the Model Color Conflict object.
        /// </summary>
        /// <param name="oModel">Model object for which Color Conflict is populated</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object in which ModelColorConflict Array resides</param>
        /// <param name="curSelColCode">Selected Color Code(can be Exterior/Interior)</param>
        /// <param name="curSelColType">Type of selected color</param>
        /// <param name="conColCode">Conflicting Color Code</param>
        /// <param name="conColType">Conflicting Color Type</param>
        /// <returns>None</returns>
        /// <exception>If any error occurs while populating the conflict, throws "Error populating Model Color Conflict"</exception>
        var oMCC = new ECModelColorConflict();
        try
        {            
            oMCC.CurrentlySelectedColorCode = curSelColCode;
            oMCC.CurrentlySelectedColorType = curSelColType;
            oMCC.ConflictingColorCode = conColCode;
            oMCC.ConflictingColorType = conColType;
            oMCC.ModelId = oModel.ModelId;
            oQueryResult.PassedValidation = false;
            oQueryResult.ModelColorConflicts.push(oMCC);
        }
        catch(e){ throw errColor3002; }
    }
                              
    this.ProcessModelOptionRules=function(sModelId, oQueryResult, sSelOpCode, bAutoApproveChanges)
    {
        /// <summary>
        /// This method is called by the ValidateConfiguration method and processes the Model Option Rules
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object</param>
        /// <param name="sSelOpCode">Selected OpCode which needs to be processed</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If true, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <returns>ECRulesEngineQueryResult</returns>
        /// <exception>If any error occurs while processing the rules, throws "Error processing Model Option Rules"</exception>
        var oECM, oSelOption;
        
        oECM = new ECConfigurationManager();
        oQueryResult.currentOption = sSelOpCode;
        
        if(oECM.AutoApproveChanges){ bAutoApproveChanges = true;}
        
        try
        {
            //Get Option object for passed in OpCode
            oSelOption = oECM.GetOption(sModelId,sSelOpCode);
            
            //Process all Rules
            
            //If a particular Option is not selected then it's SelectType is set to "Selected"
            //and the SelectedOrder counter is incremented by 1;
            if(!oSelOption.IsSelected)
            {
                oSelOption.SType = "Selected";
                if(bAutoApproveChanges)
                {
                    SelectedOrderCounter += 1;
                    oSelOption.SelectedOrder = SelectedOrderCounter;
                }
            }
            
            //Process exclude Rules
            if(!oSelOption.IsSelected)
            {
                if(oSelOption.ExcludeList.length > 0)
                {
                    this.ProcessExcludeList(sModelId,oSelOption,oECM,oQueryResult,bAutoApproveChanges);
                }    
            }
            
            //Process RequiredByList 
            if(oSelOption.RequiredByList.length > 0)
            {
                if(oSelOption.IsSelected)
                {
                    //Process required by list to make sure if an option is unselected any of the options that require it are also unselected
                    this.ProcessRequiredByListToUnselectOptions(sModelId, oSelOption, oSelOption, oECM, oQueryResult, bAutoApproveChanges);
                }
            }
            
            // process required rules
            if(oSelOption.RequiredList.length > 0)
            {
                oSelOption.OptionType = "Required";
                if(oSelOption.IsSelected)
                {
                    this.ProcessRequiredListToUnselect(sModelId,oSelOption,oSelOption, oECM,oQueryResult,bAutoApproveChanges, oSelOption.OptionType);
                }
                else
                {
                    this.ProcessRequiredListToSelect(sModelId,oSelOption,oECM,oQueryResult,bAutoApproveChanges);
                }
            }
            
            // process include rules
            if(oSelOption.IncludeList.length > 0)
            {
                oSelOption.OptionType = "Required";
                if(oSelOption.IsSelected)
                {
                    this.ProcessIncludeListToUnselect(sModelId,oSelOption,oECM,oQueryResult,bAutoApproveChanges);
                }
                else
                {
                    this.ProcessIncludeListToSelect(sModelId,oSelOption,oECM,oQueryResult,bAutoApproveChanges);
                }  
            }
            
                      
            if(oSelOption.IncludedByList.length > 0)
            {
                if(oSelOption.IsSelected)
                {
                    //Process included by list to make sure if an option is includedby any of the options that include it are also unselected
                    this.ProcessIncludeByListToUnselect(sModelId,oSelOption, oECM, oQueryResult, bAutoApproveChanges);
                }
            }
            
            // Set state of currently processed option
            if(bAutoApproveChanges)
            {
                oSelOption.OptionType = "Required";
                if(oSelOption.IsSelected)
                {
                    oSelOption.IsSelected = false;
                }    
                else
                {
                    oSelOption.IsSelected = true;
                }
            }
            else
            {
                this.currentOption = oSelOption;
            }
            
            
            
            // Process Option Color Rules
            this.ProcessOptionColorRules(sModelId, oSelOption, oECM, oQueryResult, bAutoApproveChanges);        
            
            // Update Package Information
            this.UpdatePackages(sModelId,oECM, oQueryResult);
            
            // Update Model Price
            this.CalculatePrice(sModelId,oECM);        
        
        }
        catch(e){ throw errRules4000;}
                
        // Return Query Result object
        return oQueryResult;
    }
    
    
    //This method processes the Exclude Rules
    this.ProcessExcludeList=function(sModelId,oSelOption,oECM,oQueryResult,bAutoApproveChanges)
    {
        /// <summary>
        /// This is a helper method that processes the exclude rules
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager object</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object</param>
        /// <param name="oSelOption">Selected Option which needs to be processed</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If true, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <returns>None</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>
        var oExOption;
        
        try
        {
            for(var e=0; e < oSelOption.ExcludeList.length; e++)
            {
                //Get Option object for the OpCode in the Exclude List
                oExOption = oECM.GetOption(sModelId, oSelOption.ExcludeList[e]);
                
                if(oExOption.IsSelected)
                {
                    //This scenario allows unselecting any options that are included in a package
                    this.ProcessIncludeByListToUnselect(sModelId,oExOption,oECM,oQueryResult,bAutoApproveChanges);
                    
                    if(bAutoApproveChanges)
                    {
                        //Unselect this Option by setting its IsSelected property to false
                        oExOption.IsSelected = false;
                    }
                    else
                    {
                        if(!this.CheckOptionsList("Excluded",oExOption))
                        {
                            oQueryResult.ExcludedOptions.push(oExOption);
                        }
                    }
                    
                    //If this excluded option has a required list, process required list to unselect option
                    var optionType = "Required";
                    this.ProcessRequiredListToUnselect(sModelId,oExOption,oSelOption, oECM,oQueryResult,bAutoApproveChanges,optionType);
                    
                    this.ProcessIncludeListToUnselect(sModelId,oExOption,oECM,oQueryResult,bAutoApproveChanges,optionType);
                    
                }        
            }
        }
        catch(e){ throw "Error in Process Exclude Rules";}
        
    }

    this.ProcessRequiredListToSelect = function(sModelId,oSelOption,oECM,oQueryResult,bAutoApproveChanges)
    {
        /// <summary>
        /// This is a helper method that processes the Required rules to Select Option
        /// This method is called when the state of the processed Option is not selected.
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager object</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object</param>
        /// <param name="oSelOption">Selected Option which needs to be processed</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If true, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <returns>None</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>
        var oReqOption;
        
        try
        {
            for(var i=0; i < oSelOption.RequiredList.length; i++)
            {
                //Get Option object for the OpCode in the required list
                oReqOption = oECM.GetOption(sModelId, oSelOption.RequiredList[i]);
                
                //If Option.IsSelected = false follow the process below else continue with next Option 
                if(!oReqOption.IsSelected)
                {
                    oReqOption.OptionType = "Required";
                    //Since the Required Option is not selected before and required by other option
                    //it's SelectType is set to "Required";
                    oReqOption.SType = "Required";
                    if(bAutoApproveChanges)
                    {
                        //Select the option
                        oReqOption.IsSelected = true;   
                    }
                    else
                    {
                        //Check if Option exists in RequiredOptions List
                        if(!this.CheckRequiredOptionsList(oReqOption))
                        {                                
                            oQueryResult.RequiredOptions.push(oReqOption);
                        }                    
                    }
                    
                    //Check if the Option contains an exclude list. 
                    //If true, process the Exclude Options list
                    if(oReqOption.ExcludeList.length > 0)
                    {
                        this.ProcessExcludeList(sModelId,oReqOption,oECM,oQueryResult,bAutoApproveChanges);
                    }
                }            
            }
        }
        catch(e){ throw "Error in Process Required Rules to select"; } 
    }
    
    this.ProcessRequiredListToUnselect=function(sModelId, oSelOption,oParOption, oECM, oQueryResult, bAutoApproveChanges, sOptionType)
    {
        /// <summary>
        /// This is a helper method that processes the Required rules to Unselect Option
        /// This method is called when the state of the processed Option is selected.
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager object</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object</param>
        /// <param name="oSelOption">Selected Option which needs to be processed</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If true, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <returns>None</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>        
        var oReqOption;
        try
        {
            for(var i=0; i < oSelOption.RequiredList.length; i++)
            {
                //Get Option object for the OpCode in the required list
                oReqOption = oECM.GetOption(sModelId, oSelOption.RequiredList[i]);
                
                if(oReqOption.IsSelected)
                {
                    //Process Option Required By List
                    var usedByAnOption = this.ProcessRequiredByListToCheckExcludedOptions(sModelId,oReqOption, oParOption,oECM,oQueryResult,bAutoApproveChanges,sOptionType);
                    if(!usedByAnOption)
                    {
                        if(oReqOption.SType == "Selected" && oReqOption.SelectedOrder < oSelOption.SelectedOrder)
                        {
                            //keep it selected
                        }
                        else
                        {
                            if(oReqOption.SType == "Required")
                            {
                                if(bAutoApproveChanges)
                                {
                                    oReqOption.IsSelected = false;
                                    if(sOptionType == "Required")
                                    {
                                        oReqOption.OptionType = "Required";
                                    }
                                    else
                                    {
                                        oReqOption.OptionType = "Included";
                                    }
                                }
                                else
                                {
                                    if(sOptionType == "Required")
                                    {
                                        oReqOption.OptionType = "Required";
                                    }
                                    else
                                    {
                                        oReqOption.OptionType = "Included";
                                    }
                                    if(!this.CheckOptionsList("Excluded",oReqOption))
                                    {
                                        oQueryResult.ExcludedOptions.push(oReqOption);
                                    }
                                }
                            }
                        }
                        
                        
                    }
                    else
                    {
                        for(var j=0; j < oReqOption.RequiredByList.length; j++)
                        {
                            oReqByOption = oECM.GetOption(sModelId, oReqOption.RequiredByList[j]);
                            if(oReqByOption.OpCode != oSelOption.OpCode)
                            {
                                if(oReqByOption.IsSelected)
                                {
                                    if(oReqByOption.SelectedOrder > oSelOption.SelectedOrder)
                                    {
                                        //Added check on 11/20/2008 for checking if the Option is used by any other option or not
                                        usedByAnOption = this.ProcessRequiredByListToUnselect(sModelId,oReqOption, oReqByOption,oECM,oQueryResult,bAutoApproveChanges,sOptionType);        
                                        if(!usedByAnOption)
                                        {
                                            if(bAutoApproveChanges)
                                            {
                                                oReqOption.IsSelected = false;
                                                if(sOptionType == "Required")
                                                {
                                                    oReqOption.OptionType = "Required";
                                                }
                                                else
                                                {
                                                    oReqOption.OptionType = "Included";
                                                }
                                            }
                                            else
                                            {
                                                if(sOptionType == "Required")
                                                {
                                                    oReqOption.OptionType = "Required";
                                                }
                                                else
                                                {
                                                    oReqOption.OptionType = "Included";
                                                }
                                                if(!this.CheckOptionsList("Excluded",oReqOption))
                                                {
                                                    oQueryResult.ExcludedOptions.push(oReqOption);
                                                }
                                            }
                                        }
                                    }
                                }
                            }                            
                        }
                    }                
                }        
            }    
        }
        catch(e){ throw "Error in Process Required Rules to Unselect"; }     
    }
    
    this.ProcessIncludeListToSelect=function(sModelId, oSelOption, oECM, oQueryResult, bAutoApproveChanges, sOptionType)
    {
        /// <summary>
        /// This is a helper method that processes the Include rules to Select Option
        /// This method is called when the state of the package Option is not selected.
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager object</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object</param>
        /// <param name="oSelOption">Selected Option which needs to be processed</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If true, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <param name="oOptionType">OptionType determines if the option is "Required" or "Included". It is used for price calculations</param>
        /// <returns>None</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>    
        var oIncOption;
        
        try
        {
            for(var j=0; j < oSelOption.IncludeList.length; j++)
            {
                oIncOption = oECM.GetOption(sModelId,oSelOption.IncludeList[j]);                    
                
                if(!oIncOption.IsSelected)
                {
                    this.ProcessExcludeList(sModelId, oIncOption, oECM, oQueryResult, bAutoApproveChanges);
                    if(bAutoApproveChanges)
                    {
                        oIncOption.OptionType = "Included";
                        oIncOption.SType = "Included";
                        oIncOption.IsSelected = true;
                    }
                    else
                    {                                                  
                        if(!this.CheckOptionsList("Included",oIncOption))
                        {
                            oQueryResult.IncludedOptions.push(oIncOption);
                        }
                    }
                }
                else
                {
                    oIncOption.OptionType = "Included";
                    if(oIncOption.SType != "Selected")
                    {
                        oIncOption.SType = "Included";
                    }
                }
            }
        }
        catch(e){ throw "Error in Process Included Rules to select"; } 
    }
    
    this.ProcessIncludeListToUnselect=function(sModelId, oSelOption, oECM, oQueryResult, bAutoApproveChanges, sOptionType)
    {
        /// <summary>
        /// This is a helper method that processes the Include rules to Unselect Option
        /// This method is called when the state of the package Option is selected.
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager object</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object</param>
        /// <param name="oSelOption">Selected Option which needs to be processed</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If true, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <param name="oOptionType">OptionType determines if the option is "Required" or "Included". It is used for price calculations</param>
        /// <returns>None</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>     
        
        var oIncOption, bIncluded;
        
        try
        {
            for(var u=0; u < oSelOption.IncludeList.length; u++)
            {
                oIncOption = oECM.GetOption(sModelId, oSelOption.IncludeList[u]);
                if(oIncOption.IsSelected)
                {
                    bIncluded = false;
                    //check if the Included Option is included by anyone else
                    for(var v=0; v < oIncOption.IncludedByList.length; v++)
                    {
                        //check if the Includeby opcode is different than the selected Opcode
                        if(oIncOption.IncludedByList[v] != oSelOption.OpCode)
                        {
                            var oIncByOption = oECM.GetOption(sModelId,oIncOption.IncludedByList[v]);
                            if(oIncByOption.IsSelected)
                            {
                                bIncluded = true;
                                break;                                
                            }                           
                        }
                                                    
                    }
                    if(!bIncluded)
                    {
                        if(bAutoApproveChanges)
                        {
                             //Change the Option Type to required
                            oIncOption.OptionType = "Required";
                            //Change option state to unselected
                            oIncOption.IsSelected = false;                            
                        }
                        else
                        {
                            if(!this.CheckOptionsList("Excluded",oIncOption))
                            {
                                oQueryResult.ExcludedOptions.push(oIncOption);
                            }
                        }
                    }
                }
            }
        }
        catch(e){ throw "Error in Process Included Rules to select"; } 
    }
    
    this.ProcessRequiredByListToUnselectOptions=function(sModelId, oOption, oSelOption, oECM, oQueryResult, bAutoApproveChanges)
    {
        /// <summary>
        /// This is a helper method that processes the RequiredBy rules to Unselect Option
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager object</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object</param>
        /// <param name="oOption">Option which is processed to see if it is required by anyone</param>
        /// <param name="oSelOption">Selected Option which needs to be processed</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If true, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <returns>Boolean result flag</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>   
                
        var bResult = false;      
        var oModel = oECM.GetModel(sModelId);
        var aOptions = new Array();
        
        try
        {
            if(oModel != null)
            {            
                //Loop through the options to get all the options that require this option
                for(var i=0; i < oModel.ModelOptionList.length; i++)
                {
                    //Loop through all the Requiredlist to see if the option is required by other options
                    for(j=0; j < oModel.ModelOptionList[i].RequiredList.length; j++)
                    {
                        //checks the required list of an option contains the passed in option opcode
                        if(oModel.ModelOptionList[i].RequiredList[j] == oOption.OpCode)
                        {
                            //checks if the Option which requires the objOption is
                            //the same as the parent Option (selectedOption) passed in
                            if(oModel.ModelOptionList[i].OpCode != oSelOption.OpCode)
                            {
                                if(oModel.ModelOptionList[i].IsSelected)
                                {
                                    aOptions.push(oModel.ModelOptionList[i]);
                                    bResult = true; 
                                    //return bResult;
                                }
                                                              
                            }
                        }
                    }
                 }
             }
         }
         catch(e){ throw "Error in Process RequiredBy Rules to Unselect"; } 
         if(aOptions.length > 0)
         {
            for(var k=0; k < aOptions.length; k++)
            {
                if(bAutoApproveChanges)
                {
                    aOptions[k].IsSelected = false;
                }
                else
                {
                    if(!this.CheckOptionsList("Excluded",aOptions[k]))
                    {
                        oQueryResult.ExcludedOptions.push(aOptions[k]);
                    }
                }
            }
         }         
    }
    
    this.ProcessRequiredByListToUnselect=function(sModelId, oOption, oSelOption, oECM, oQueryResult, bAutoApproveChanges)
    {
        /// <summary>
        /// This is a helper method that processes the RequiredBy rules to Unselect Option
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager object</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object</param>
        /// <param name="oOption">Option which is processed to see if it is required by anyone</param>
        /// <param name="oSelOption">Selected Option which needs to be processed</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If true, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <returns>Boolean result flag</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>   
                
        var bResult = false;      
        var oModel = oECM.GetModel(sModelId);
        
        try
        {
            if(oModel != null)
            {            
                //Loop through the options to get all the options that require this option
                for(var i=0; i < oModel.ModelOptionList.length; i++)
                {
                    //Loop through all the Requiredlist to see if the option is required by other options
                    for(var j=0; j < oModel.ModelOptionList[i].RequiredList.length; j++)
                    {
                        //checks the required list of an option contains the passed in option opcode
                        if(oModel.ModelOptionList[i].RequiredList[j] == oOption.OpCode)
                        {
                            //checks if the Option which requires the objOption is
                            //the same as the parent Option (selectedOption) passed in
                            if(oModel.ModelOptionList[i].OpCode != oSelOption.OpCode)
                            {
                                if(oModel.ModelOptionList[i].IsSelected)
                                {
                                    bResult = true; 
                                    return bResult;
                                }
                                                              
                            }
                        }
                    }
                 }
             }
         }
         catch(e){ throw "Error in Process RequiredBy Rules to Unselect"; } 
         
         return bResult;
    }
    
    this.ProcessRequiredByListToCheckExcludedOptions=function(sModelId, oOption, oSelOption, oECM, oQueryResult, bAutoApproveChanges)
    {
        /// <summary>
        /// This is a helper method that processes the RequiredBy rules to Unselect Option
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager object</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object</param>
        /// <param name="oOption">Option which is processed to see if it is required by anyone</param>
        /// <param name="oSelOption">Selected Option which needs to be processed</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If true, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <returns>Boolean result flag</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>   
                
        var bResult = false;      
        var oModel = oECM.GetModel(sModelId);
        
        try
        {
            if(oModel != null)
            {            
                //Loop through the options to get all the options that require this option
                for(var i=0; i < oModel.ModelOptionList.length; i++)
                {
                    //Loop through all the Requiredlist to see if the option is required by other options
                    for(var j=0; j < oModel.ModelOptionList[i].RequiredList.length; j++)
                    {
                        //checks the required list of an option contains the passed in option opcode
                        if(oModel.ModelOptionList[i].RequiredList[j] == oOption.OpCode)
                        {
                            //checks if the Option which requires the objOption is
                            //the same as the parent Option (selectedOption) passed in
                            if(oModel.ModelOptionList[i].OpCode != oSelOption.OpCode)
                            {
                                if(oModel.ModelOptionList[i].IsSelected)
                                {
                                    if(this.CheckOptionsListInQueryResult("Excluded",oModel.ModelOptionList[i],oQueryResult))
                                    {
                                        bResult = false; //Return false since the Option is already in ExcludedOption
                                    }
                                    else
                                    {
                                        bResult  = true; //If the Option is not in Excluded Option, return true;
                                    }
                                    return bResult;
                                }
                                                              
                            }
                        }
                    }
                 }
             }
         }
         catch(e){ throw "Error in Process RequiredBy Rules to Unselect"; } 
         
         return bResult;
    }
    
    this.ProcessIncludeByListToUnselect=function(sModelId,oSelOption, oECM, oQueryResult, bAutoApproveChanges)
    {
        /// <summary>
        /// This is a helper method that processes the IncludedBy rules to Unselect Option
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager object</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object</param>
        /// <param name="oSelOption">Selected Option which needs to be processed</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If true, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <returns>Boolean result flag</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>     
        var oModel, oIncOption;
        oModel = oECM.GetModel(sModelId);
        
        try
        {
            //Loop through the options to get all the options that include this option
            for(var i=0; i < oModel.ModelOptionList.length; i++)
            {
                //Loop through all the Includelist to see if the option is included by other options
                for(var j=0; j < oModel.ModelOptionList[i].IncludeList.length; j++)
                {
                    //checks the include list of an option contains the passed in option opcode
                    if(oModel.ModelOptionList[i].IncludeList[j] == oSelOption.OpCode)
                    {
                        if(oModel.ModelOptionList[i].IsSelected)
                        {
                            if(bAutoApproveChanges)
                            {
                                oModel.ModelOptionList[i].IsSelected = false;
                            }
                            else
                            {
                                if(oModel.ModelOptionList[i].IsSelected)
                                {
                                    //Add Option to ExcludedOptions List
                                    if(!this.CheckOptionsList("Excluded",oModel.ModelOptionList[i]))
                                    {
                                        oQueryResult.ExcludedOptions.push(oModel.ModelOptionList[i]);
                                    }
                                }
                            }
                            //Loop through the include options for this particular option
                            for(var k=0; k < oModel.ModelOptionList[i].IncludeList.length; k++)
                            {   
                                if(oModel.ModelOptionList[i].IncludeList[k] != oSelOption.OpCode)
                                {
                                    oIncOption = oECM.GetOption(sModelId,oModel.ModelOptionList[i].IncludeList[k]);
                                    if(oIncOption.IsSelected)
                                    {
                                        if(bAutoApproveChanges)
                                        {
                                            oIncOption.IsSelected = false;
                                        }
                                        else
                                        {
                                            if(oIncOption.IsSelected)
                                            {
                                                //Add Option to ExcludedOptions List
                                                if(!this.CheckOptionsList("Excluded",oIncOption))
                                                {
                                                    oQueryResult.ExcludedOptions.push(oIncOption);
                                                }
                                            }
                                        }                                    
                                        this.ProcessRequiredListToUnselect(sModelId, oIncOption, oSelOption, oECM, oQueryResult, bAutoApproveChanges,"Included");
                                    }
                                }
                            }
                        }
                    }
                }
             }
         }
         catch(e){ throw "Error in Process IncludedBy Rules to Unselect"; } 
         
    }
    
    this.ProcessOptionColorRules=function(sModelId, oSelOption, oECM, oQueryResult, bAutoApproveChanges)
    {
        /// <summary>
        /// This is a helper method that processes the Option Color Rules
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager object</param>
        /// <param name="oQueryResult">ECRulesEngineQueryResult object</param>
        /// <param name="oSelOption">Selected Option which needs to be processed</param>
        /// <param name="bAutoApproveChanges">
        /// Boolean flag to determine if conflicts need to be sent to the caller or not. 
        /// If false, the conflicts are returned back to the caller. If true, the conflicts are resolved and the user can get the new state.
        ///</param>
        /// <returns>Boolean result flag</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>        
        var oModel = oECM.GetModel(sModelId);
        var oSelExtColor;
        var oSelIntColor;
        var oRequiredOptions;
        
        oSelExtColor = oECM.GetSelectedExteriorColor(sModelId);
        oSelIntColor = oECM.GetSelectedInteriorColor(sModelId);            
        
        try
        {
            //If bAutoApproveChanges is true, then get the selected Options and check for any color conflicts
            //Else process option color conflict for currently processed option and all RequiredOptions
            if(bAutoApproveChanges)
            {
                for(var l=0; l < oModel.ModelOptionList.length; l++)
                {
                    if(oModel.ModelOptionList[l].IsSelected)
                    {
                        this.CheckForOptionColorConflicts(sModelId, oModel.ModelOptionList[l] , oSelExtColor, oSelIntColor, oQueryResult);
                    }
                }
            }
            else
            {
                //check for option color conflicts for currently selected option
                this.CheckForOptionColorConflicts(sModelId, oSelOption , oSelExtColor, oSelIntColor, oQueryResult);
                oRequiredOptions = oQueryResult.RequiredOptions;
                
                if(oRequiredOptions != null)
                {
                    for(var j=0; j < oRequiredOptions.length; j++)
                    {
                        this.CheckForOptionColorConflicts(sModelId, oRequiredOptions[j], oSelExtColor, oSelIntColor, oQueryResult);
                    }
                }                   
            }
        }
        catch(e){ throw "Error in Process Option Color Rules ";}  
    }
    
    
    
    this.CheckForOptionColorConflicts=function(sModelId, oOptionToProcess, oSelExtColor, oSelIntColor, oQueryResult)
    {
        /// <summary>
        /// This is a helper method that checks the Option Color conflicts. If any conflicts arises, it calls the PopulateOptionColorConflict
        /// method to populate the conflict.
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oOptionToProcess">Option for which Color Conflict Rules are processed</param>
        /// <param name="oSelExtColor">Currently selected Exterior Color</param>
        /// <param name="oSelIntColor">Currently selected Interior Color</param>
        /// <returns>Boolean result flag</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>      
                
        var extPassed = false;
        var intPassed = false;
        
        try
        {
            if(oOptionToProcess.OptionColorList.length > 0)
            {
                for(var iCol=0; iCol < oOptionToProcess.OptionColorList.length; iCol++)
                {   
                    if(oOptionToProcess.OptionColorList[iCol].ColorType == "E")
                    {
                        intPassed = true;
                        if(oSelExtColor != null)
                        {
                            if(oOptionToProcess.OptionColorList[iCol].ColorIdent == oSelExtColor.ColorIdent)
                            {
                                //Select the part number
                                oOptionToProcess.OptionColorList[iCol].IsSelected = true;
                                extPassed = true;
                                break;
                            }
                        }
                    }
                    else if(oOptionToProcess.OptionColorList[iCol].ColorType == "I")
                    {
                        extPassed = true;
                        if(oSelIntColor != null)
                        {
                            if(oOptionToProcess.OptionColorList[iCol].ColorIdent == oSelIntColor.ColorIdent)
                            {
                                //Select the part number
                                oOptionToProcess.OptionColorList[iCol].IsSelected = true;
                                intPassed = true;
                                break;
                            }
                        }
                    }
                }
                if(!extPassed){ this.PopulateOptionColorConflict(sModelId, oOptionToProcess, oSelExtColor, "E", oQueryResult);}
                if(!intPassed){ this.PopulateOptionColorConflict(sModelId, oOptionToProcess, oSelIntColor, "I", oQueryResult);}
            }            
        }
        catch(e){ throw "Error in Check Option Color Conflicts "; } 
        
    }
    
    this.PopulateOptionColorConflict=function(sModelId, oOption, oColor, sColorType, oQueryResult)
    {
        
        var oOCC = new ECOptionColorConflict();
        oOCC.ModelId = sModelId;
        if(oOption != null)
        {
            oOCC.OpCode = oOption.OpCode;
        }
        else
        {
            oOCC.OpCode = "No OpCode Passed";
        }
        if(oColor != null)
        {
            if(oColor.ColorType == "E")
            {
                oOCC.ColorCode = oColor.ColorMfgCode; 
            }
            else
            {
                oOCC.ColorCode = oColor.ColorCode; 
            } 
        }
        else
        {
            oOCC.ColorCode = "None";            
        }
        oOCC.ColorType = sColorType;
        oQueryResult.PassedValidation = false;
        oQueryResult.OptionColorConflicts.push(oOCC);            
    }
    
    this.UpdatePackages=function(sModelId, oECM, oQueryResult)
    {
        /// <summary>
        /// This is a helper method that updates the package information. It populates the currently selected options within the package.
        /// It also calculates the selected accessory count and unselected accessory count.
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager</param>
        /// <returns>Boolean result flag</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>          
        var oModel = oECM.GetModel(sModelId);
        var iSelCnt = 0; 
        var iNotSelCnt = 0; 
        var fSelPrice = 0;
        try
        {
            for(var n=0; n < oModel.ModelOptionPackageList.length; n++)
            {
                for(var m=0; m < oModel.ModelOptionList.length; m++)
                {
                    if(oModel.ModelOptionList[m].OpCode == oModel.ModelOptionPackageList[n].OpCode)
                    {
                        if(oModel.ModelOptionList[m].IsSelected){oModel.ModelOptionPackageList[n].IsSelected = true;}
                        else{oModel.ModelOptionPackageList[n].IsSelected = false;}
                    }
                    for(var k=0; k < oModel.ModelOptionPackageList[n].IncludedOptionsList.length; k++)
                    {
                        if(oModel.ModelOptionList[m].OpCode == oModel.ModelOptionPackageList[n].IncludedOptionsList[k].OpCode)
                        {
                            if(oModel.ModelOptionList[m].IsSelected)
                            {
                                oModel.ModelOptionPackageList[n].IncludedOptionsList[k].IsSelected = true;
                                fSelPrice += parseFloat(oModel.ModelOptionList[m].OptionPrice);
                                iSelCnt +=1;
                            }
                            else
                            {
                                oModel.ModelOptionPackageList[n].IncludedOptionsList[k].IsSelected = false;
                                iNotSelCnt +=1;      
                            }
                        }
                    }                        
                }
                oModel.ModelOptionPackageList[n].TotalSelectedOptions = iSelCnt;
                oModel.ModelOptionPackageList[n].TotalSelectedPrice = fSelPrice;
                
                fSelPrice = 0;
                iSelCnt=0;
                iNotSelCnt=0;
            }
            oQueryResult.Packages = oModel.ModelOptionPackageList;
        }
        catch(e){ throw "Error in UpdatePackages " + e.Message;}
    }
    
    this.CalculatePrice = function(sModelId, oECM)
    {
        /// <summary>
        /// This is a helper method that calculates the total price of the current configuration. 
        /// </summary>
        /// <param name="sModelId">ModelId of the Model for which Option Rules are processed</param>
        /// <param name="oECM">Instance of ECConfigurationManager</param>
        /// <returns>Boolean result flag</returns>
        /// <exception>If any error occurs while processing the rules, throws error by appending this method name</exception>          
       
        var totalPrice = 0;
        var oModel = oECM.GetModel(sModelId);
        
        totalPrice = parseFloat(oModel.MSRP);
        
        for(var p=0; p < oModel.ModelOptionList.length; p++)
        {
            if(oModel.ModelOptionList[p].IsSelected)
            {
                if(oModel.ModelOptionList[p].OptionType == "Required")
                {
                    totalPrice += parseFloat(oModel.ModelOptionList[p].OptionPrice);
                }
                if(oModel.ModelOptionList[p].OptionColorList.length > 0)
                {
                    for(var q=0; q < oModel.ModelOptionList[p].OptionColorList.length; q++)
                    {
                        if(oModel.ModelOptionList[p].OptionColorList[q].IsSelected)
                        {
                            pricedelta =  parseFloat(oModel.ModelOptionList[p].OptionColorList[q].PriceDelta);
                            totalPrice += isNaN(pricedelta)?0:pricedelta;
                        }
                    }                    
                }
            }
        }        
        oModel.TotalPrice = totalPrice;        
    }
    
    this.CheckRequiredOptionsList=function(oOption)
    {
        /// <summary>
        /// This is a helper method that checks if the option passed in is in Required Options List or not
        /// </summary>
        /// <param name="oOption">Option to be verified</param>
        /// <returns>Boolean result flag</returns>
        /// <exception>None</exception>          
       
        var bResult = false;
        var oQueryResult = new ECRulesEngineQueryResult();
        var aRequiredOptions = oQueryResult.RequiredOptions;
        if(aRequiredOptions.length > 0)
        {
            for(var i=0; i < aRequiredOptions.length; i++)
            {
                if(aRequiredOptions[i] == oOption)
                {
                    bResult = true;
                }
            }
            
        }
        return bResult;
    }
    
   
    this.CheckOptionsList=function(listType, oOption)
    {
        /// <summary>
        /// This is a helper method that checks if the passed in option is in the array or not.
        /// </summary>
        /// <param name="oOption">option to be verified</param>
        /// <returns>Boolean result flag</returns>
        /// <exception>None</exception>          
       
        var bResult = false;
        var oQueryResult = new ECRulesEngineQueryResult();
        var aOptions;
        
        switch(listType){
        case "Required":
            aOptions = oQueryResult.RequiredOptions;
            break;
        case "Included":
            aOptions = oQueryResult.IncludedOptions;
            break;
        case "Excluded":
            aOptions = oQueryResult.ExcludedOptions;
            break;
        default:break;       
        }
        
        if(aOptions.length > 0)
        {
            for(var i=0; i < aOptions.length; i++)
            {
                if(aOptions[i] == oOption)
                {
                    bResult = true;
                }
            }
        }
        
        return bResult;
    }


    this.CheckOptionsListInQueryResult=function(listType, oOption, oQueryResult)
    {
        /// <summary>
        /// This is a helper method that checks if the passed in option is in the array or not.
        /// </summary>
        /// <param name="oOption">option to be verified</param>
        /// <returns>Boolean result flag</returns>
        /// <exception>None</exception>          
       
        var bResult = false;
        var aOptions;
        
        switch(listType){
        case "Required":
            aOptions = oQueryResult.RequiredOptions;
            break;
        case "Included":
            aOptions = oQueryResult.IncludedOptions;
            break;
        case "Excluded":
            aOptions = oQueryResult.ExcludedOptions;
            break;
        default:break;       
        }
        
        if(aOptions.length > 0)
        {
            for(var i=0; i < aOptions.length; i++)
            {
                if(aOptions[i] == oOption)
                {
                    bResult = true;
                }
            }
        }
        
        return bResult;
    }
}

function GetColorMatchedAssets(sModelId, arAssets){
    var aAssetsReturn = [];
    var eccm = new ECConfigurationManager();
    var exColorObj = eccm.GetSelectedExteriorColor(sModelId);
    
    for(var i=0;i<arAssets.length;i++){
        for(var k=0;k<arAssets[i].AssetColorList.length;k++){
            if(arAssets[i].AssetColorList[k].ColorMfgCode == exColorObj.ColorMfgCode){
                if(!aAssetsReturn.contains(arAssets[i])){
                    aAssetsReturn.push(arAssets[i]);
                }
                break;
            }
        }
    }
    
    if (aAssetsReturn.length == 0){
        for(var i=0;i<arAssets.length;i++){
            if (arAssets[i].AssetColorList.length == 0){
                if(!aAssetsReturn.contains(arAssets[i])){
                    aAssetsReturn.push(arAssets[i]);
                }
            }
        }
    }
    
    return aAssetsReturn;
}

function ConstructModel(modelJSON, modelId, exColorCd, inColorCd, accIdArray){
    
    var eccm = new ECConfigurationManager();
    
    if (modelJSON){
        if (eccm.ModelList.length > 0) {
            eccm.ClearModelState(modelId);
        }
        eccm.AddModels(modelJSON);
        eccm.ProcessModelColorRules(modelId, exColorCd, inColorCd);
        
        for(var i=0;i<accIdArray.length;i++){
        
            if (accIdArray[i] != "" && accIdArray[i] != "null"){
            
                eccm.ProcessModelOptionRules(modelId, accIdArray[i], true);
            }
        }
    }
    
    return eccm;
}

function GetPartNumber(modelId, exColorCd){
    var eccm = new ECConfigurationManager();
    var selectedOptions = eccm.GetCurrentlySelectedOptions(modelId);
    for(var i=0;i<selectedOptions.length;i++){
        var colorList = selectedOptions[i].OptionColorList;
        for(var x=0;x<colorList.length;x++){
            if (colorList[x].ColorMfgCode == exColorCd){
                return colorList[x].PartNumber;
            }
        }
    }
    return "";
}

var srcElement=null;
var srcElementURL = '';
var alertId = "exitPageAlert";
var OldOnClickFunction=null;

$(document).ready(function(){
    if(document.onclick) OldOnClickFunction=document.onclick;
    if(!document.all) document.captureEvents(Event.CLICK);
    document.onclick=processLeavingToolClick;
});

function processLeavingToolClick(e){
    if(!e) e=event;
    srcElement=null;
    if(e.srcElement) srcElement=e.srcElement;
    if(e.target) srcElement=e.target;

    // Determine if the link clicked was in div#HeaderContainer or div#FooterContainer.
    // These are "exit" links    
    var tmpsrcElement = srcElement;
    if (srcElement) {        
        var bExitLink = false;                
        var bContinue = true;
        while (bContinue) {
            if ( (tmpsrcElement.id == 'HeaderContainer') || (tmpsrcElement.id == 'FooterContainer') ) {
                bExitLink = true;
            }
            if (tmpsrcElement.parentNode) {
                tmpsrcElement = tmpsrcElement.parentNode;
            } else {
                bContinue = false;
            }            
        }
        
        // The element might have a parent who is an anchor (in the case of something like an IMG).
        if ( (srcElement.parentNode) && (srcElement.parentNode.tagName=="A") ) {
            srcElement = srcElement.parentNode;
        }

        if (bExitLink) {
            // This element should be an anchor
            if ( (srcElement.tagName=="A") ) {
                if(!srcElement.onclick){                
                    srcElementURL = srcElement.href;
                    if (srcElementURL.indexOf("javascript:")==-1 && srcElementURL.indexOf("#")==-1 && srcElementURL.indexOf("build-price")==-1) {
                        // Show the layer that will ask the user if they want to leave or not
                        tb_show("", "#TB_inline?height=163&width=400&inlineId=exitPageAlert&modal=true", "");
                        $(".TB_modal").css({padding: "0px"});
                        var wAdj = 21;
                        var hAdj = ($.browser.safari) ? 30 : 20;
                        $("#TB_window").css({width: $("#exitPageAlertMain").width() + wAdj + "px", height: "auto"});
                        $("#TB_ajaxContent").css({width: $("#exitPageAlertMain").width() + wAdj + "px", height: "auto"});
                        return false;
                    }
                }
            }
        }
    }

    return true;
    e.cancelBubble=true;
    if(e.stopPropagration) e.stopPropagation();
    if(OldOnClickFunction) OldOnClickFunction();
    return false;
}

// Called when the user cancels
function StayHere(){
    tb_remove();
}

// Called when the user wants to leave
function LeaveHere(){
    if (srcElementURL != '') {
        top.location.href=srcElementURL;
    }
}

//GENERAL
function SetCanvas(folderName , modelYear){
    var modelFolderPath = "/images/" + modelYear + "/" + folderName;
    $("#canvasHeader").attr("src", modelFolderPath + "/headers/build-price.jpg");
    $("body").css({background: "url(" + modelFolderPath + "/background.jpg) repeat-x"});
}

function showPrevConfigs(){
    $("#prevConfigsPopup").css({display: "block"});
    setTimeout(function(){$("#prevConfigsPopup").animate({marginTop: "0px"}, 700);}, 300);
}

function retractPrevConfigs(callback){
    setTimeout(function(){
        $("#prevConfigsPopup").animate({marginTop: "-100px"}, 500, callback);
    }, 10);
}

function StartOver(source){
    tb_show("", "#TB_inline?height=180&width=400&inlineId=startoverPopup&modal=true", "");
    $(".TB_modal").css({padding: "0px"});
    $("#TB_window").css({width: "400px"});
    
    // Tracking 
    switch (source) {
        case 'trim':
            s.linkTrackVars = 'prop26,prop27,prop37,eVar26,eVar27';
            s.prop26 = 'MODEL';
            s.prop27 = 'RESET';
            s.prop37 = 'BUILD & PRICE:MODEL:DEFAULT:B&P - SELECT A MODEL';
            CallSDotTL(s , true , 'BUILD & PRICE:MODEL:RESET:START OVER LINK' , 'o');
            break;
        case 'color':
            s.linkTrackVars = 'prop26,prop27,prop37,eVar26,eVar27';
            s.prop26 = 'COLORS';
            s.prop27 = 'RESET';
            s.prop37 = 'BUILD & PRICE:COLORS:DEFAULT:B&P - SELECT COLORS';
            CallSDotTL(s , true , 'BUILD & PRICE:COLORS:RESET:START OVER LINK' , 'o');
            break;
        case 'accessories':
            s.linkTrackVars = 'prop26,prop27,prop37,eVar26,eVar27';
            s.prop26 = 'ACCESSORIES';
            s.prop27 = 'RESET';
            s.prop37 = 'BUILD & PRICE:ACCESSORIES:DEFAULT:B&P - SELECT ACCESSORIES';
            CallSDotTL(s , true , 'BUILD & PRICE:ACCESSORIES:RESET:START OVER LINK' , 'o');
            break;
    }

}

//SUMMARY PAGE
function LoadModelInfoForDisplay(){
    var exColorIndex = 0;
    var inColorIndex = 0;
    for(var x=0;x<=exColorList.length-1;++x){
        if (exColorList[x][1] == sEColor){
            exColorIndex = x;
        }
    }
    for(var x=0;x<=inColorList.length-1;++x){
        if (inColorList[x][1] == sIColor){
            inColorIndex = x;
        }
    }
    
    //LEFT COLUMN - INFO
    var exColorName = "";
    var inColorName = "";
    $.each(exColorList, function(){
        if (this[6] == sEColor){
            exColorName = this[0];
        }
    });
    $.each(inColorList, function(){
        if (this[1] == sIColor){
            inColorName = this[0];
        }
    });
    $("#trimName").html("<div class=\"subTitle\">" + sModelYear + " " + trimList[0][3] + " " + DedupeModelTrim(trimList[0][3], trimList[0][0]) + "</div><div style=\"margin-top: 2px; text-align: right;\"><b>" + removeDecimal(modelList[0][2]) + "</b>&nbsp;&nbsp;&nbsp;<div class=\"clr\"></div></div>");
    $("#colorNames").html("<div class=\"subTitle\">Exterior: " + exColorName + "<br />" + "Interior: " + inColorName + "</div><div><div class=\"clr\"></div></div>");
    $("#dhCost").html(removeDecimal(modelList[0][3]));
    
    var accHtml =  $("#accContainer").html();
    if (sSelected != ""){
        var accSplit = sSelected.split(",");
        var pkgAccHtml = "<div class=\"lineItem\"><b class=\"big\">Package</b></div>";
        var exAccHtml = "<div class=\"lineItem\"><b class=\"big\">Exterior</b></div>";
        var inAccHtml = "<div class=\"lineItem\"><b class=\"big\">Interior</b></div>";
        var electAccHtml = "<div class=\"lineItem\"><b class=\"big\">Electronic</b></div>";
        var eccm = ConstructModel(ConfigurableModelJSON, sModelID, sEColor, sIColor, sSelected.split(","));
        var oModel = eccm.GetModel(sModelID);
        $.each(accSplit, function(){
            var accId = this;
            var accFound = false;
            $.each(packageList, function(){
                if (this[1] == accId){
                    accFound = true;
                    pkgAccHtml += "<div class=\"lineItem\"><div class=\"title\">" + this[0] + "</div><div style=\"text-align: right;\"><b>" + removeDecimal(this[2]) + "</b></div><div style=\"margin-top: 5px;\">";
                    
                    $.each(oModel.ModelOptionPackageList, function(){
                        if (this.OpCode == accId){
                            var accArrays = exteriorAccList.concat(interiorAccList, electronicAccList);
                            $.each(this.IncludedOptionsList, function(){
                                var includedAccId = this.OpCode;
                                $.each(accArrays, function(){
                                    if (this[1] == includedAccId){
                                        pkgAccHtml += "<div style=\"text-indent: 20px;\">" + this[0] + "</div>";
                                        return false;
                                    }
                                });
                            });
                        }
                    });
                    
                    pkgAccHtml += "</div></div>";
                    return false;
                }
            });
            if (!accFound){
                $.each(exteriorAccList, function(){
                    if (this[1] == accId){
                        accFound = true;
                        exAccHtml += "<div class=\"lineItem\"><div class=\"title\">" + this[0] + "</div><div style=\"text-align: right;\"><b>" + removeDecimal(this[2]) + "</b></div></div>";
                        return false;
                    }
                });
            }
            if (!accFound){
                $.each(interiorAccList, function(){
                    if (this[1] == accId){
                        accFound = true;
                        inAccHtml += "<div class=\"lineItem\"><div class=\"title\">" + this[0] + "</div><div style=\"text-align: right;\"><b>" + removeDecimal(this[2]) + "</b></div></div>";
                        return false;
                    }
                });
            }
            if (!accFound){
                $.each(electronicAccList, function(){
                    if (this[1] == accId){
                        accFound = true;
                        electAccHtml += "<div class=\"lineItem\"><div class=\"title\">" + this[0] + "</div><div style=\"text-align: right;\"><b>" + removeDecimal(this[2]) + "</b></div></div>";
                        return false;
                    }
                });
            }
        });
        
        var addHtml = "";
        if (pkgAccHtml != "<div class=\"lineItem\"><b class=\"big\">Package</b></div>"){
            addHtml += pkgAccHtml;
        }
        if (exAccHtml != "<div class=\"lineItem\"><b class=\"big\">Exterior</b></div>"){
            addHtml += exAccHtml;
        }
        if (inAccHtml != "<div class=\"lineItem\"><b class=\"big\">Interior</b></div>"){
            addHtml += inAccHtml;
        }
        if (electAccHtml != "<div class=\"lineItem\"><b class=\"big\">Electronic</b></div>"){
            addHtml += electAccHtml;
        }
        $("#accContainer").html(accHtml + addHtml + "<br />");
    }else{
        $("#accContainer").html(accHtml + "<div class=\"txtDiv1\"><div class=\"subHeader\">You did not add any accessories.</div></div><br />");
    }
    
    //MIDDLE COLUMN - PHOTOS
    ShowCarPhoto("", sEColor, sIColor, true);
    setTimeout(function(){
        AddRemoveAccOverlays(true);
    }, 100);
    
    $("#interiorPhoto").html("<img src='" + inColorList[inColorIndex][3] + "' width='300px' />");    
    
    //RIGHT COLUMN - OTHER INFO
    $("#similarModels").html("Similar " + trimList[0][3] + " Models");
    for (var i = 0; i < similarModelList.length; i++) {
        if (i == 1) {
            $("#similarList")[0].innerHTML += '<br />';
        }
        $("#similarList")[0].innerHTML += "<a href=\"colors.aspx?ModelName=" + sModelName + "&ModelYear=" + sModelYear + "&ModelID=" + similarModelList[i][0] + "\"  onclick=\"TrackBNPClick(s , 'BUILD & PRICE:SUMMARY:NEW B&P:BUILD A SIMILAR MODEL LINK' , 'SUMMARY' , 'NEW B&P' , 'prop1,prop2,prop5,prop33,products,eVar10,eVar11,eVar14,eVar16');\">" + similarModelList[i][1] + " (" + removeDecimal(similarModelList[i][2]) + " )</a>";
    }

    
    
    // Confirmation
    $("#similarModels2").html("Similar " + trimList[0][3] + " Models");
    
    for (var i = 0; i < similarModelList.length; i++) {
        if (i == 1) {
            $("#similarList2")[0].innerHTML += '<br />';
        }
        $("#similarList2")[0].innerHTML += "<a href=\"colors.aspx?ModelName=" + sModelName + "&ModelYear=" + sModelYear + "&ModelID=" + similarModelList[i][0] + "\"  onclick=\"TrackBNPClick(s , 'BUILD & PRICE:QUOTE:NEW B&P:BUILD A SIMILAR MODEL LINK' , 'QUOTE' , 'NEW B&P' , 'prop1,prop2,prop5,prop33,products,eVar10,eVar11,eVar14,eVar16');\">" + similarModelList[i][1] + " (" + removeDecimal(similarModelList[i][2]) + " )</a>";
    }
    
    $("#dlBroLink").html("Download the " + trimList[0][3] + " brochure (PDF)");
    $("#dlFsLink").html("Download the " + trimList[0][3] + " fact sheet (PDF)");
    $("#goHomeLink").html("Go to " + trimList[0][3] + " home page");
    $("#goHomeLink").attr("href", "/" + sModelFolderName);
    $("#dlBroLink2").html("Download the " + trimList[0][3] + " brochure (PDF)");
    $("#dlFsLink2").html("Download the " + trimList[0][3] + " fact sheet (PDF)");
    $("#goHomeLink2").html("Go to " + trimList[0][3] + " home page");
    $("#goHomeLink2").attr("href", "/" + sModelFolderName);
}

function BNPRequestAQuote(dealerId){
    var dealerInfo = "";
    var tyDealerInfo = "";
    var dealerName = "";
    
    var d = new Date();
    var weekday = new Array(7);
    weekday[0]="Sunday";
    weekday[1]="Monday";
    weekday[2]="Tuesday";
    weekday[3]="Wednesday";
    weekday[4]="Thursday";
    weekday[5]="Friday";
    weekday[6]="Saturday";
    
    var curr_hour = d.getHours();
    var curr_min = d.getMinutes()+"";
    var a_p = (curr_hour < 12) ? "AM" : "PM";
    if (curr_hour == 0){
        curr_hour = 12;
    }
    if (curr_hour > 12){
        curr_hour = curr_hour - 12;
    }
    if (curr_min.length == 1){
        curr_min = "0" + curr_min;
    }
    
    $.each(dealerList, function(){
        if (this[0] == dealerId){
            dealerInfo = "<b>" + this[1] + "</b><br/>" + this[4] + "<br/>" + this[5] + ", " + this[6] + " " + this[7].substr(0, this[7].indexOf("-")) +
                "<br/>" + this[3] + "<br/><a href=\"mailto:" + this[8] + "\">Contact Internet Manager</a>" + "<span id=\"chosenDealerId\" style=\"display: none;\">" + dealerId + "</span>";
            tyDealerInfo = "<b style=\"color: #000;\">" + this[1] + "</b><br/>" + this[4] + "<br/>" + this[5] + ", " + this[6] + " " + this[11] +
                "<br/>" + this[3] + "<br/><br/><b style=\"color: #000;\">Manager:</b><br/>" + this[7] + "<br/><br/><b style=\"color: #000;\">Request sent on:</b><br/>" +
                weekday[d.getDay()] + " " + (d.getMonth() + 1) + "/" + d.getDate() + "/" + d.getFullYear() + " " + curr_hour + ":" + curr_min + " " + a_p +
                "<span id=\"chosenDealerId\" style=\"display: none;\">" + dealerId + "</span>";
            dealerName = this[1];
        }
    });
    
    $("#raqDealerInfo").html(dealerInfo);
    $("#tyDealerData").html(tyDealerInfo);
    $("#dealerName3").html(dealerName);
    
    tb_show("","raq_preloader.aspx?width=612&height=447&TB_iframe=true&modal=true","");
    
    // Track Link
    var sOldProp26 = s.prop26;
    var sOldProp27 = s.prop27;
    var sOldProp37 = s.prop37;
    s.linkTrackVars = 'prop26,prop27,prop37,prop39,eVar7,eVar26,eVar27';
    s.prop26 = 'SUMMARY';
    s.prop27 = 'QUOTE REQUEST';
    s.prop39 = dealerId;
    CallSDotTL(s , true , 'BUILD & PRICE:SUMMARY:QUOTE REQUEST:REQUEST A QUOTE LINK' , 'o');
    s.prop26 = sOldProp26;
    s.prop27 = sOldProp27;
    s.prop37 = sOldProp37;

    
    // Track form
    s.pageName = 'B&P - QUOTE REQUEST';
    s.prop26 = 'QUOTE';
    s.prop27 = 'DEFAULT';
    s.prop37 = 'BUILD AND PRICE:QUOTE:DEFAULT:B&P - QUOTE REQUEST';
    s.prop39 = dealerId;
    s.eVar3 = 'B&P - QUOTE REQUEST';
    s.events = 'event7';
    CallSDotT(s);
}


$(document).ready(function(){
    var finalCurrentModelsHTML = "";
    var finalPreviousModelsHTML = "";
    
    for(var i=0;i<=modelGroupList.length-1;++i){
        var divHtmlStr = "";
        var hasOffer = false;
        
        $.each(offersList, function(){
            if ($(this)[7].indexOf(modelGroupList[i][0]) > -1){ hasOffer = true; return false; }
        });
        
        divHtmlStr += "<div id=\"hover_model_" + modelGroupList[i][1] + "_" + modelGroupList[i][0].replace(/ /g, "") +
                            "\" class=\"modelDisplayBox\" style=\"background: url('/images/tools/shopping/models-display-bg-off.jpg') no-repeat;\">";
        
        divHtmlStr += "<div style=\"position: absolute; left: 0px; top: 0px; width: 215px; height: 70px; z-index: 0;\"><img modelGroupListIndex=\"" + i + "\"  id=\"click_modelimage_" + modelGroupList[i][1] + "_" + modelGroupList[i][0].replace(/ /g, "") + "\" src=\"" + modelGroupList[i][5] + "\" width=\"215\" height=\"70\"></div>";
        
        if (hasOffer){
            divHtmlStr += "<div class=\"modelOffer\"><a href=\"javascript:ShowCurrentOffer('" + modelGroupList[i][0] + "', '" + modelGroupList[i][1] + "');\"><img alt=\"Offer\" title=\"Offer\" src=\"/images/tools/build-price/icon-offer.png\" height=\"17px\" width=\"17px\" /></a></div>";
        }
        
        divHtmlStr += "<div modelGroupListIndex=\"" + i + "\" id=\"click_model_" + modelGroupList[i][1] + "_" + modelGroupList[i][0].replace(/ /g, "") + "\" style=\"position: absolute; z-index: 10; display: block;\">";
        divHtmlStr += "<div class=\"car-text\">" + modelGroupList[i][1] + " " + modelGroupList[i][0] + " ";
        divHtmlStr += "<span>Starting at</span> " + removeDecimal(modelGroupList[i][4]) + "<sup>[1]</sup><br/><span>" + modelGroupList[i][7];
        divHtmlStr += " | Seating for " + modelGroupList[i][6] + "</span></div></div></div>";
        
        if (modelGroupList[i][2].toLowerCase() == "false"){
            finalPreviousModelsHTML += divHtmlStr;
        }else{
            finalCurrentModelsHTML += divHtmlStr;
        }
    }
    
    if (finalCurrentModelsHTML != ""){
        $("#currentModelsDiv").html(finalCurrentModelsHTML);
    }
    if (finalPreviousModelsHTML != ""){
        $("#prevModelsHeader").css({display: "block"});
        $("#previousModelsDiv").html(finalPreviousModelsHTML);
    }
    
    for(var i=0;i<=modelGroupList.length-1;++i){
        var modelDivHover = $("#hover_model_" + modelGroupList[i][1] + "_" + modelGroupList[i][0].replace(/ /g, ""));
        var modelDivClick = $("#click_model_" + modelGroupList[i][1] + "_" + modelGroupList[i][0].replace(/ /g, ""));
        var modelImageDivClick = $("#click_modelimage_" + modelGroupList[i][1] + "_" + modelGroupList[i][0].replace(/ /g, ""));
        
        modelDivClick.click(function(){
            chosenModelIndex = parseInt($(this).attr("modelGroupListIndex"));
            checkForChange();
        });        
        modelImageDivClick.click(function(){
            chosenModelIndex = parseInt($(this).attr("modelGroupListIndex"));
            checkForChange();
        });
        
        modelDivHover.hover(function(){
            var newBG = $(this).css("background").replace("-off", "-over");
            $(this).css({background: newBG});
        },
        function(){
            var newBG = $(this).css("background").replace("-over", "-off");
            $(this).css({background: newBG});
        });
    }
});

var chosenModelIndex = -1;
function checkForChange(){
    if (chosenModelIndex != null && chosenModelIndex > -1){
        if (window.location.search.indexOf("ModelName") > -1 && ($.getQueryString({id:"ModelName"}) != modelGroupList[chosenModelIndex][0] || $.getQueryString({id:"ModelYear"}) != modelGroupList[chosenModelIndex][1])){
            $("#newSelection").html(modelGroupList[chosenModelIndex][1] + " " + modelGroupList[chosenModelIndex][0]);
            $("#oldSelection").html($.getQueryString({id:"ModelYear"}) + " " + $.getQueryString({id:"ModelName"}));
            var wAdj = $.browser.msie ? 380 : 400;
            var hAdj = $.browser.safari ? 272 : 280;
            tb_show("", "#TB_inline?height=" + hAdj + "&width=" + wAdj + "&inlineId=changeModelPopup&modal=true", "");
            $(".TB_modal").css({padding: "0px"});
            $("#TB_window").css({width: wAdj + "px"});
        }else{        
            moveOn("ModelName|ModelYear");
        }
    }
}

function moveOn(qsToRemove){
    if (chosenModelIndex != null && chosenModelIndex > -1){
        GoForwardBack(ForwardPage, QueryStringsToAdd + "ModelName/" + modelGroupList[chosenModelIndex][0] + "|ModelYear/" + modelGroupList[chosenModelIndex][1], qsToRemove);
        chosenModelIndex = -1;
    }
}

function triggerModelClickFromTB(modelName, modelYear){
    var t = $("#click_model_" + modelYear + "_" + modelName.replace(/ /g, ""));
    if (t.length == 1){
        tb_remove();
        setTimeout(function(){
            t.trigger("click");
        }, 300);
    }
}

var filters = [];

$(document).ready(function(){
    SetListItems(".side-nav > li", "modelFilters");
});

function FilterModels(filterCheckbox){
    var validCats = [];
    
    if (filterCheckbox){
        var filterVal = cleanVal(filterCheckbox.value);
        
        //UPDATE FILTERS LIST
        if (filterCheckbox.checked){
            filters.push(filterVal);
        } else {
            var indexToRemove = -1;
            for (var i=0;i<=filters.length-1;i++){
                if (filters[i] == filterVal) { indexToRemove = i; }
            }
            if (indexToRemove > -1) { filters.remove(indexToRemove); }
        }
    }else{
        filters.length = 0;
    }
    
    if (filters.length == 0){
        $("#filterResetButton").css({display: "none"});
    }else{
        $("#filterResetButton").css({display: "block"});
    }
    
    setTimeout(function(){
        //DO FILTERING
        for (var y=0;y<=modelGroupList.length-1;y++){
            var show = true;
            var modelCatsVal = cleanVal(modelGroupList[y][8]);
            var element = "#hover_model_" + modelGroupList[y][1] + "_" + modelGroupList[y][0].replace(/ /g,"");
            
            for (var x=0;x<=filters.length-1;x++){
                if (modelCatsVal.indexOf(filters[x]) == -1){
                    show = false;
                    break;
                }
            }
            
            if (show && !validCats.contains(modelCatsVal)){
                validCats.push(modelCatsVal);
            }
            
            if (show && !$(element).is(":visible")){
                $(element).show(400);
            }else if (!show && $(element).is(":visible")){
                $(element).hide(600);
            }
        }
        
        //ENABLE/DISABLE INVALID FILTERS
        $("li > input").each(function(){
            var enable = false;
            
            for (var i=0;i<=validCats.length-1;i++){
                if (validCats[i].indexOf(cleanVal($(this).val())) > -1){
                    enable = true;
                    break;
                }
            }
            
            if (enable && $(this)[0].disabled){
                SwitchListItemActive($(this).attr("id"));
            }else if (!enable && !$(this)[0].disabled){
                SwitchListItemActive($(this).attr("id"));
            }
        });
    }, 1);
}

function ResetFilter(){
    FilterModels();
    
    $("input:checked").each(function(){
        SwitchListItemFromCheckbox($(this).attr("id"));
    });
}

function cleanVal(dirtyVal){
    return dirtyVal.toLowerCase().replace(/ /g, "")
}

//PRICE TAG
//
//These functions handle showing the shopping tool's price tag, as well as setting its text
function ShowPricetag(){
    $("#priceTag").animate({marginTop: "0px"}, 1000, "easeOutBounce");
}

function RetractPricetag(){
    $("#priceTag").animate({marginTop: "-200px"}, 500);
}

function FormatCurrency(sNum) {
        sNum = sNum.toString().replace(/\$|\,/g,'');
    	
        if(isNaN(sNum))
	        sNum = "0";
    	
        var sTemp = sNum;
    	
        var bSign = (Number(sNum) == (sNum = Math.abs(sNum)));
        sNum = Math.floor(sNum*100+0.50000000001);
        var sCents = sNum%100;
        sNum = Math.floor(sNum/100).toString();
    	
        if(sCents<10)
	        sCents = "0" + sCents;

        for (var i = 0; i < Math.floor((sNum.length-(1+i))/3); i++)
	        sNum = sNum.substring(0,sNum.length-(4*i+3))+ ',' + sNum.substring(sNum.length-(4*i+3));

        return (((bSign)?'':'-') + '$' + sNum + '.' + sCents);
    }
    
function setPriceTag(msrp, dhCost, ModelYear, ModelName, Trim, Trans,modelid,enableLeasing){
    setTimeout(function(){
        var priceTagContent = '';
        
        priceTagContent += "<div id='priceTagContent'>";
        priceTagContent += "<div class='priceTagLeft'>";        
        priceTagContent += "<div class='priceTagTitle'>" + ModelYear + " " + ModelName + "&nbsp<span class='mname'>" + DedupeModelTrim(ModelName,Trim) + "</span></div>";
        priceTagContent += "<div class='priceTagTransmission'>" + Trans + " Transmission</div>";
        priceTagContent += "<div class='priceTagStandardFeatures'><a href='javascript:standardFeatures(\"" + ModelName + "\", \"" + ModelYear + "\",\"" + modelid + "\");'>Standard Features</a></div>";
        priceTagContent += "</div>";
        
        priceTagContent += "<div class='priceTagRight'>";
        priceTagContent += "<div class='priceTagPrice' id='priceTagPrice'>" + removeDecimal(calcMsrp(msrp, dhCost)) + "</div>";
        priceTagContent += "<div class='priceTagMSRPLabel'>Total MSRP<sup>[ 2 ]</sup></div>";        
        priceTagContent += "</div>";
        
        priceTagContent += "<div class='clr'></div>";
        priceTagContent += "<div class='monthlyPaymentDiv'>Monthly Payments &nbsp;&nbsp;&nbsp;&nbsp;<a href='javascript:EstimatePayments(\"" + modelid + "\", \"" + msrp + "\", \"" + "testing" + "\", \"" + dhCost + "\");'>Calculate</a> | <a id='showLink' href='javascript:priceTagInfoToggle();'>Show</a></div>";
        priceTagContent += "<div class='monthlyPaymentDiv' style='margin-left:190px;margin-top:5px;'><a href='javascript:priceTagInfoToggle();'><img id='imgToggle' src='/images/tools/finance-tools/arrow-show.gif' /></a></div>";
        
        priceTagContent += "<div class='priceTagCalculateField'>";
        priceTagContent += "<div class='tit'>Lease It</div>";        
        priceTagContent += "<div class='sub'>Estimated Monthly Payment</div>";        
        priceTagContent += "<div id='priceTagLeaseMonthly' class='calcPrice'>$---.--</div>";        
        priceTagContent += "</div>";
        
        priceTagContent += "<div class='priceTagCalculateField' style='margin-left:15px;'>";
        priceTagContent += "<div class='tit'>Finance It</div>";        
        priceTagContent += "<div class='sub'>Estimated Monthly Payment</div>";        
        priceTagContent += "<div id='priceTagFinanceMonthly' class='calcPrice'>$---.--</div>";        
        priceTagContent += "</div><div id='CompareResults'></div>";
        
        priceTagContent += "</div>";
        priceTagContent += "<div><img src='/images/tools/shopping/pricetag-bottom.gif'></div>";
        
        $("#priceTag").html(priceTagContent);
        EstimatePayments(modelid,msrp,"",dhCost,ModelName);
    }, 100);
    
}


//PAYMENT ESTIMATOR
function EstimatePayments(modelid,price,title,dhCost,mGroup){
    if ( title == "" ) {
        var CVars = new CalcVars(mGroup);
        CVars.load();

        $("#CompareResults").load('/handlers/tools/shopping/comparecalculator.ashx?msrp='+ price +'&fterm='+ CVars.FTerm +'&lterm='+CVars.LTerm+'&downpayment='+CVars.DownPayment+'&mileage='+CVars.Mileage+'&apr='+CVars.APR+'&modelid='+modelid+'&tradein='+ CVars.TradeInVal +'&owed='+CVars.TradeInOwed + '&dc=' + dhCost, function(data) {
            if (CalResult[0][0] == '0') { 
                $("#priceTagLeaseMonthly").html( "$" + CalResult[0][2]);
                $("#priceTagFinanceMonthly").html( "$" + CalResult[0][1]);
                if ( CalResult[0][1] == '0' ) parent.$(".priceTagFinanceMonthly").html("$--");
                if ( CalResult[0][2] == '0' ) parent.$("#priceTagLeaseMonthly").html("$--");                
            } else {
                $("#ErrorMsg").html(CalResult[0][1]);
            }
        });
    }
    else {
            tb_show("","/tools/finance-tools/payment-estimator-pop-up.aspx?title=" + title.replace(/\ /g,'%20') + "&price=" + price + "&modelid=" + modelid + "&dc=" + dhCost + "&width=750&amp;TB_iframe=true&amp;height=570&amp;modal=true","");
    }
}

function CalcVars(ModelGroup,Certified) {

    this.ModelGroup = ModelGroup;
    this.APR = '5';
    this.CertifiedAPR = '12';
    this.FTerm = '60';
    this.LTerm = '36';
    this.DownPayment = '0';
    this.Mileage = "12,000";
    this.TradeInVal = '0';
    this.TradeInOwed = '0';
    this.Certified = Certified;
    
    this.load = function() {
        if ( GetCookie("calculatorVars") ) {
            var arr = GetCookie("calculatorVars").split(";");
            if(this.ModelGroup == arr[0].split("=")[1]) {
                if( arr[1].split("=")[1] != "") this.APR = arr[1].split("=")[1];
                if( arr[2].split("=")[1] != "") this.FTerm = arr[2].split("=")[1];
                if( arr[3].split("=")[1] != "") this.LTerm = arr[3].split("=")[1];
                if( arr[4].split("=")[1] != "") this.DownPayment = arr[4].split("=")[1];
                if( arr[5].split("=")[1] != "") this.Mileage = arr[5].split("=")[1];
                if( arr[6].split("=")[1] != "") this.TradeInVal = arr[6].split("=")[1];
                if( arr[7].split("=")[1] != "") this.TradeInOwed = arr[7].split("=")[1];
                if( arr[8].split("=")[1] != "") this.CertifiedAPR = arr[8].split("=")[1];
                if( this.Certified = true ) { this.APR == this.CertifiedAPR }
            }
        }
    }
    
    this.save = function() {
        var CookieTxt = "";
        CookieTxt += "ModelID=" + this.ModelGroup + ";";
        CookieTxt += "APR=" + this.APR + ";";
        CookieTxt += "FTerm=" + this.FTerm + ";";
        CookieTxt += "LTerm=" + this.LTerm + ";";
        CookieTxt += "DownPayment=" + this.DownPayment + ";";
        CookieTxt += "Mileage=" + this.Mileage + ";";
        CookieTxt += "TradeInVal=" + this.TradeInVal + ";";
        CookieTxt += "TradeInOwed=" + this.TradeInOwed + ";";
        CookieTxt += "CertifiedAPR=" + this.CertifiedAPR;
        SetCookie("calculatorVars", CookieTxt);
    }
}

function priceTagInfoToggle() {
    if ( $("#imgToggle")[0].src.indexOf("-show.gif") != -1 ) {
        $("#imgToggle")[0].src = $("#imgToggle")[0].src.replace("-show.gif","-hide.gif");
        $("#priceTagContent").animate({height:"135px"},500);
        $("#showLink").text("Hide");
    }
    else {
        $("#imgToggle")[0].src = $("#imgToggle")[0].src.replace("-hide.gif","-show.gif");
        $("#priceTagContent").animate({height:"90px"},500);
        $("#showLink").text("Show");
    }
}

//STANDARD FEATURES
function standardFeatures(modelname,year,modelid) {
    modelname = (!modelname || modelname == "") ? sModelName : modelname;
    year = (!year || year == "") ? sModelYear : year;
    modelid = (!modelid || modelid == "") ? sModelID : modelid;
    tb_show("","/tools/standard-features-pop-up.aspx?name=" + modelname.replace(/\ /g,'%20') + "&year=" + year + "&id=" + modelid + "&width=801&amp;TB_iframe=true&amp;height=490&amp;modal=true","")
    
    // Tracking
    var sTempPageName = s.pageName;
    var sTempChannel = s.channel;
    var sTempProp26 = s.prop26;
    var sTempProp27 = s.prop27;
    var sTempProp37 = s.prop37;
    var sTempEvents = s.events;
    s.pageName = 'STANDARD FEATURES';
    s.channel = 'FEATURES';
    s.prop26 = 'STANDARD';
    s.prop27 = 'DEFAULT';
    s.prop37 = 'FEATURES:STANDARD:DEFAULT:STANDARD FEATURES';
    s.events = '';
    CallSDotT(s);
    // Put old variables back for links
    s.pageName = sTempPageName;
    s.channel = sTempChannel;
    s.prop26 = sTempProp26;
    s.prop27 = sTempProp27;
    s.prop37 = sTempProp37;
    s.events = sTempEvents;

}

//DETAIL BUBBLE
//
//These functions handle the detail panel that slides out from behind the shopping tools menu
var canvasMenuSlideSpeed = 400;

//detailHTML is the HTML to be placed inside the detail bubble
function SlideDetailBubble(detailHTML){
    if (!$("#detail-bubble").is(":visible")){
        $("#detail-bubble").html(detailHTML);
        setTimeout(function(){$("#detail-bubble").css({display: "block"}).animate({left: "363px"}, canvasMenuSlideSpeed);}, 25);
    }
}

function ExpandDetailBubble(detailHTML){
    if (!$("#detail-bubble").is(":visible")){
        $("#detail-bubble").css({left: "363px"}).html(detailHTML).show(canvasMenuSlideSpeed);
    }
}

function AdjustDetailBubble(detailHTML, autoAdjustSize){
    if (autoAdjustSize == null){ autoAdjustSize = true; }
    
    if ($("#detail-bubble").is(":visible")){
        $("#pre-detail-change").html(detailHTML);
        setTimeout(function(){
            if (autoAdjustSize){
                $("#detail-bubble").animate({height: ($("#pre-detail-change")[0].offsetHeight - 20) + "px"}, canvasMenuSlideSpeed).html($("#pre-detail-change").html());
            }else{
                 $("#detail-bubble").html($("#pre-detail-change").html());
            }
        }, 25);
    }
}

function ShowDetailBubble(detailHTML, forceShow){
    if (!$("#detail-bubble").is(":visible") || forceShow){
        $("#detail-bubble").html(detailHTML);
        setTimeout(function(){ $("#detail-bubble").css({display: "block", left: "363px"}); }, 25);
    }
}

function HideDetailBubble(){
    if ($("#detail-bubble").is(":visible")){
        $("#detail-bubble").stop(true, true).css({display: "none", left: "0px", height: ""}).html("");
    }
}

//To animate hiding the detail bubble - companion to SlideDetailBubble
function SlideOutDetailBubble(){
    if ($("#detail-bubble").is(":visible")){
        setTimeout(HideDetailBubble, canvasMenuSlideSpeed - 100);
        $("#detail-bubble").animate({left: "0px"}, canvasMenuSlideSpeed);
    }
}

//To animate hiding the detail bubble - companion to ExpandDetailBubble
function ShrinkOutDetailBubble(){
    if ($("#detail-bubble").is(":visible")){
        setTimeout(HideDetailBubble, canvasMenuSlideSpeed + 25);
        $("#detail-bubble").hide(canvasMenuSlideSpeed);
    }
}

//CHECKBOX LIST
//
//This function handles the task of adding functionality to listitems with checkboxes as children
//
//matchStr is the jquery selector to use to find the listitems on the page (ie ".side-nav > li")
//listType is a string used to distinguish what happens when the li is clicked
function SetListItems(matchStr, listType){
    $(matchStr).each(function(){
        $(this).mouseover(function(){
            $(this).addClass('select');
        }).mouseout(function(){
            if (!this.firstChild.checked){
                $(this).removeClass('select');
            }
        }).click(function(){
            if (!$(this).is(".inactiveCbLi")){
                $(this).addClass('select');
                this.firstChild.checked = !this.firstChild.checked;
                if (listType == "modelFilters"){
                    FilterModels(this.firstChild);
                }
                if (listType == "accList"){
                    SwapAccSelection($(this.firstChild).val(), this.firstChild.checked);
                }
            }
        }).children().click(function(){
            this.checked = !this.checked;
        });
    });
}

//The checkbox in a Checkbox List has the id on it - so if you find that you need to select a list item
//in a Checkbox List dynamically, you can do so with this function
//
//checkboxId - the id of the checkbox who's parent list-item you need to set as selected
function SwitchListItemFromCheckbox(checkboxId){
    if ($("#" + checkboxId).length > 0){
        if (!$("#" + checkboxId)[0].checked){
            $("#" + checkboxId).parent().addClass('select');
            $("#" + checkboxId)[0].checked = true;
        }else{
            $("#" + checkboxId).parent().removeClass('select');
            $("#" + checkboxId)[0].checked = false;
        }
    }
}

//In some cases it may be necessary to prevent a checkbox list item from being selectable - this function toggles
//an item's selectability
//
//checkboxId - the id of the checkbox who's parent list-item you need to set as inactive
function SwitchListItemActive(checkboxId){
    if ($("#" + checkboxId).length > 0){
        if ($("#" + checkboxId)[0].disabled){
            $("#" + checkboxId).attr("disabled", "");
            $("#" + checkboxId).parent().removeClass('inactiveCbLi');
        }else{
            $("#" + checkboxId).attr("disabled", "disabled");
            $("#" + checkboxId).parent().addClass('inactiveCbLi');
        }
    }
}

//BASE CAR PHOTO
//
//This function builds the base car photo, as well as the front/rear buttons
//
//exColorId is a string value of the exterior color id, if known - Optional
//inColorId is a string value of the interior color id, if known - Optional
//givenModelId is a string value of model id, if it's not apart of the query string yet (ie on the trims page) - Optional
function ShowCarPhoto(givenModelId, exColorId, inColorId, smallerSize){
    var modelId = "";
    if (givenModelId && givenModelId != ""){
        modelId = givenModelId;
    }else{
        modelId = (sModelID == "null") ? "" : sModelID;
    }
    
    var modelListIndex = (modelId == "") ? (modelList.length - 1) : -1;
    if (modelListIndex == -1){
        for(var i=0;i<modelList.length;++i){
            if (modelList[i][1] == modelId){
                modelListIndex = i;
            }
        }
    }

    if (modelListIndex > -1) {
        var frontPhotoPath = GetBaseCarPhotoPath(modelListIndex, exColorId, inColorId, "FRONT");
        var rearPhotoPath = GetBaseCarPhotoPath(modelListIndex, exColorId, inColorId, "REAR");
        
        var tempFrontImg = new Image();
        var tempRearImg = new Image();
        tempFrontImg.src = frontPhotoPath;
        tempRearImg.src = rearPhotoPath;
        
        setTimeout(function(){
            AddPhotoDivs(frontPhotoPath, rearPhotoPath, smallerSize);
            
            $("#frontViewBtn").unbind();
            $("#rearViewBtn").unbind();
            $("#frontViewBtn").click(function(){ SwitchCarPhoto("FRONT"); });
            $("#rearViewBtn").click(function(){ SwitchCarPhoto("REAR"); });
        }, 100);
    }
}

//switchTo - either "FRONT" or "REAR"
function SwitchCarPhoto(switchTo){
    switchTo = (switchTo && switchTo != "") ? switchTo.toUpperCase() : "FRONT";
    var currentPhotoType = $("#rearPhotosDiv").is(":visible") ? "REAR" : "FRONT";
    var doSwitch = true;
    
    if (currentPhotoType != switchTo){
        if (currentPhotoType == "FRONT"){
            currentPhotoType = "REAR";
            $("#frontViewBtn").attr("src", "/images/tools/build-price/btn-frontview.gif");
            $("#frontViewBtn").css({cursor: "pointer"});
            $("#rearViewBtn").attr("src", "/images/tools/build-price/btn-rearview-select.gif");
            $("#rearViewBtn").css({cursor: "default"});
        }else if (currentPhotoType == "REAR"){
            currentPhotoType = "FRONT";
            $("#frontViewBtn").attr("src", "/images/tools/build-price/btn-frontview-select.gif");
            $("#frontViewBtn").css({cursor: "default"});
            $("#rearViewBtn").attr("src", "/images/tools/build-price/btn-rearview.gif");
            $("#rearViewBtn").css({cursor: "pointer"});
        }
    }else{
        doSwitch = false;
    }
    
    if (doSwitch){
        $("#frontPhotosDiv").animate({opacity: "toggle"}, 600);
        $("#rearPhotosDiv").animate({opacity: "toggle"}, 600);
    }
}

//type is a string: either "FRONT" or "REAR" - defaults to "FRONT"
function GetBaseCarPhotoPath(modelListIndex, exColorId, inColorId, type){
    var path = "";
    type = (type == null || type == "") ? "FRONT" : type.toUpperCase();
    
    if (!exColorId || exColorId == "" || modelList[modelListIndex][6].indexOf(exColorId) == -1){
        for(var i=0;i<exColorList.length;++i){
            if (modelList[modelListIndex][6].indexOf(exColorList[i][6]) > -1){
                exColorId = exColorList[i][6];
                break;
            }
        }
    }
    
    var exInColors = "";
    $.each(exColorList, function(){
        if(this[6] == exColorId){
            exInColors = this[5];
            return false;
        }
    });
    
    var modelStartIndex = exInColors.indexOf(modelList[modelListIndex][1] + "~");
    var modelEndIndex = exInColors.substr(modelStartIndex).indexOf("/");
    
    var modelExInColors = "";
    if (modelEndIndex == -1){
        modelExInColors = exInColors.substr(modelStartIndex);
    }else{
        modelExInColors = exInColors.substr(modelStartIndex, (modelEndIndex - modelStartIndex));
    }
    
    if (exInColors != "" && (!inColorId || inColorId == "" || modelExInColors.indexOf(inColorId) == -1)){
        var indexStartInColors = modelExInColors.indexOf("~")+1;
        var endFirstInColor = modelExInColors.indexOf("|");
        
        if (endFirstInColor == -1){
            inColorId = modelExInColors.substr(indexStartInColors);
        }else{
            inColorId = modelExInColors.substr(indexStartInColors, (endFirstInColor - indexStartInColors));
        }
    }
    
    $.each(baseCarPhotoList, function(){
        if (modelList[modelListIndex][5].indexOf($(this)[0]) > -1){                
            if ($(this)[2].indexOf(exColorId) > -1 && $(this)[2].indexOf(inColorId) > -1){            
                if ($(this)[1].indexOf(type) > -1){
                    path = $(this)[1];
                }
            }
        }
    });
    
    return path;
}

var photoCount = 0;
function AddPhotoDivs(frontPhotoPath, rearPhotoPath, smallerSize){
    if (smallerSize){
        frontPhotoPath = GetCarImageSize(frontPhotoPath, 300, 200);
        rearPhotoPath = GetCarImageSize(rearPhotoPath, 300, 200);
    }
    
    var frontSRC = $.browser.msie ? "/images/trans.gif" : escape(frontPhotoPath);
    var rearSRC = $.browser.msie ? "/images/trans.gif" : escape(rearPhotoPath);
    var imageSizeStyle = smallerSize ? "height: 200px; width: 300px;" : "height: 450px; width: 550px;";
    
    if ($("#threeQuartFrontImg").length == 0){
        var frontPhoto = "<div id=\"threeQuartFrontImg\"><div id=\"front" + photoCount + "\" style=\"position: absolute;\"><img id=\"frontImg\" src=\"" + frontSRC + "\" style=\"" + imageSizeStyle + " filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + escape(frontPhotoPath) + "',sizingMethod='scale');\" /></div></div>";
        var rearPhoto = "<div id=\"threeQuartRearImg\"><div id=\"rear" + photoCount + "\" style=\"position: absolute;\"><img id=\"rearImg\" src=\"" + rearSRC + "\" style=\"" + imageSizeStyle + " filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + escape(rearPhotoPath) + "',sizingMethod='scale');\" /></div></div>";
        var frBtns = "<img id=\"frontViewBtn\" style=\"cursor: default;\" alt=\"FRONT\" title=\"FRONT\" src=\"/images/tools/build-price/btn-frontview-select.gif\" /><img id=\"rearViewBtn\" alt=\"REAR\" title=\"REAR\" src=\"/images/tools/build-price/btn-rearview.gif\" />";
        
        if ($("#frontPhotosDiv").length > 0){ $("#frontPhotosDiv").html(frontPhoto); }
        if ($("#rearPhotosDiv").length > 0){ $("#rearPhotosDiv").html(rearPhoto); }
        if ($("#photoBtnsDiv").length > 0){ $("#photoBtnsDiv").html(frBtns); }
    }else{
        if ($("#frontImg").attr("src") != frontSRC){
            var existPhotoNum = photoCount;
            ++photoCount;
            var newPhotoNum = photoCount;
            
            var frontHTML = $("#threeQuartFrontImg").html();
            $("#threeQuartFrontImg").html(frontHTML + "<div id=\"front" + newPhotoNum + "\" style=\"display: none; position: absolute;\"><img id=\"frontImg\" src=\"" + frontSRC + "\" style=\"" + imageSizeStyle + " filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + escape(frontPhotoPath) + "',sizingMethod='scale');\" /></div>");
            $("#front" + newPhotoNum).fadeIn(600);
            setTimeout(function(){
                $("#front" + existPhotoNum).fadeOut(700, function(){
                    $("#front" + existPhotoNum).remove();
                });
            }, 150);
            
            var rearHTML = $("#threeQuartRearImg").html();
            $("#threeQuartRearImg").html(rearHTML + "<div id=\"rear" + newPhotoNum + "\" style=\"display: none; position: absolute;\"><img id=\"rearImg\" src=\"" + rearSRC + "\" style=\"" + imageSizeStyle + " filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + escape(rearPhotoPath) + "',sizingMethod='scale');\" /></div>");
            $("#rear" + newPhotoNum).fadeIn(600);
            setTimeout(function(){
                $("#rear" + existPhotoNum).fadeOut(700, function(){
                    $("#rear" + existPhotoNum).remove();
                });
            }, 150);
        }
        
        //$("#threeQuartFrontImg > img").attr("src", frontSRC);
        //$("#threeQuartRearImg > img").attr("src", rearSRC);
        //$("#threeQuartFrontImg > img").attr("style", "" + imageSizeStyle + " filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + escape(frontPhotoPath) + "',sizingMethod='scale');");
        //$("#threeQuartRearImg > img").attr("style", "" + imageSizeStyle + " filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + escape(rearPhotoPath) + "',sizingMethod='scale');");
    }
}

//FORWARD/BACKWARD BUTTONS
//
//Since the shopping controls are shared between Build and Price, Request a Quote, etc.
//we needed a way to get their back/next buttons to go to different places.  The solution was to put javascript variables
//on each page that the controls would assume were there.  Those variables are called:
//ForwardPage
//BackwardPage
//QueryStringsToAdd
//QueryStringsToRemove
//So a call to this function from one of the shopping controls might be:  GoForwardBack(ForwardPage, QueryStringsToAdd) or GoForwardBack(BackwardPage, "", QueryStringsToRemove)
//
//newPage is the name of the page you're going to (ie ForwardPage or BackwardPage) - example: "models.aspx"
//queryStringsToAdd is a pipe separated string of the name/value pairs (separated by a forward-slash just like that) of query strings to add, if any - example: "modelId/1234R|modelYear/1900"
//queryStringsToRemove is a pipe separated string of the names of query strings to remove, if any - example: "modelId|modelYear"
function GoForwardBack(newPage, queryStringsToAdd, queryStringsToRemove, source){
    var tempQueryStr = window.location.search;
    var winLoc = window.location.toString().replace(tempQueryStr, "");
    
    if (queryStringsToAdd && queryStringsToAdd != "" && tempQueryStr != ""){
        //First, check for their existence in the current url
        var pairs = queryStringsToAdd.split("|");
        $.each(pairs, function(){
            var pair = this.split("/");
            if (tempQueryStr.indexOf(pair[0]) > -1){
                queryStringsToRemove += "|" + pair[0];
            }
        });
    }
    if (queryStringsToRemove && tempQueryStr != ""){
        //Next, remove all query strings to be removed
        var names = queryStringsToRemove.split("|");
        $.each(names, function(){
            if (tempQueryStr.indexOf(this) > -1){
                var removeVal = $.getQueryString({id:this});
                var removeStr = this + "=" + removeVal;
                tempQueryStr = tempQueryStr.replace(removeStr, "").replace(removeStr.replace(/ /g, "%20"), "");
                tempQueryStr = tempQueryStr.replace("&&", "&").replace("?&", "?");
            }
        });
    }
    if (queryStringsToAdd && queryStringsToAdd != ""){
        //Last, add all query strings to be added
        var pairs = queryStringsToAdd.split("|");
        $.each(pairs, function(){
            var pair = this.split("/");
            if (pair.length == 2){
                if (tempQueryStr.length == 0){
                    tempQueryStr += "?" + pair[0] + "=" + pair[1];
                }else{
                    tempQueryStr += "&" + pair[0] + "=" + pair[1];
                }
            }
        });
    }
    
    tempQueryStr = tempQueryStr.length > 1 ? tempQueryStr.replace("&&", "&").replace("?&", "?") : "";
    tempQueryStr = tempQueryStr.lastIndexOf("&") == tempQueryStr.length-1 ? tempQueryStr.substr(0,tempQueryStr.length-1) : tempQueryStr;
    
    TrackNavigationChange(source);
    
    documentDotLocation(newPage + tempQueryStr);
}

function TrackNavigationChange(source) {

    // Tracking based on source
    s.linkTrackVars = 'prop26,prop27,prop37,eVar26,eVar27';
    switch (source) {
        case 'raq_1_vehandzip':
            s.prop26 = 'COLORS';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'RAQ:COLORS:DEFAULT:RAQ - SELECT COLORS';
            CallSDotTL(s , true , 'RAQ:COLORS:BACKWARD:VEHICLE & ZIP CODE TOP NAV LINK' , 'o');
            break;
        case 'raq_2_vehandzip':
            s.prop26 = 'DEALER';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'RAQ:DEALER:DEFAULT:RAQ - SELECT A DEALER';
            CallSDotTL(s , true , 'RAQ:DEALER:BACKWARD:VEHICLE & ZIP CODE TOP NAV LINK' , 'o');
            break;
        case 'raq_3_vehandzip':
            s.prop26 = 'CONTACT';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'RAQ:CONTACT:DEFAULT:RAQ - ENTER CONTACT INFORMATION';
            CallSDotTL(s , true , 'RAQ:CONTACT:BACKWARD:VEHICLE & ZIP CODE TOP NAV LINK' , 'o');
            break;
        case 'raq_2_colors':
            s.prop26 = 'DEALER';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'RAQ:DEALER:DEFAULT:RAQ - SELECT A DEALER';
            CallSDotTL(s , true , 'RAQ:DEALER:BACKWARD:COLORS TOP NAV LINK' , 'o');
            break;
        case 'raq_3_colors':
            s.prop26 = 'CONTACT';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'RAQ:CONTACT:DEFAULT:RAQ - ENTER CONTACT INFORMATION';
            CallSDotTL(s , true , 'RAQ:CONTACT:BACKWARD:COLORS TOP NAV LINK' , 'o');
            break;
        case 'raq_1_dealer':
            s.prop26 = 'COLORS';
            s.prop27 = 'FORWARD';
            s.prop37 = 'RAQ:COLORS:DEFAULT:RAQ - SELECT COLORS';
            CallSDotTL(s , true , 'RAQ:COLORS:FORWARD:DEALER TOP NAV LINK' , 'o');
            break;
        case 'raq_3_dealer':
            s.prop26 = 'CONTACT';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'RAQ:CONTACT:DEFAULT:RAQ - ENTER CONTACT INFORMATION';
            CallSDotTL(s , true , 'RAQ:CONTACT:BACKWARD:DEALER TOP NAV LINK' , 'o');
            break;
        case 'raq_colors_back':
            s.prop26 = 'COLORS';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'RAQ:COLORS:DEFAULT:RAQ - SELECT COLORS';
            CallSDotTL(s , true , 'RAQ:COLORS:BACKWARD:BACK LINK' , 'o');
            break;
        case 'raq_colors_nextbtn':
            s.prop26 = 'COLORS';
            s.prop27 = 'FORWARD';
            s.prop37 = 'RAQ:COLORS:DEFAULT:RAQ - SELECT COLORS';
            CallSDotTL(s , true , 'RAQ:COLORS:FORWARD:NEXT:SELECT A DEALER LINK' , 'o');
            break;
        case 'bnp_colors_back':
            s.prop26 = 'COLORS';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:COLORS:DEFAULT:B&P - SELECT COLORS';
            CallSDotTL(s , true , 'BUILD & PRICE:COLORS:BACKWARD:BACK LINK' , 'o');
            break;
        case 'bnp_colors_nextbtn':
            s.prop26 = 'COLORS';
            s.prop27 = 'FORWARD';
            s.prop37 = 'BUILD & PRICE:COLORS:DEFAULT:B&P - SELECT COLORS';
            CallSDotTL(s , true , 'BUILD & PRICE:COLORS:FORWARD:NEXT:ACCESSORIES LINK' , 'o');
            break;
        case 'bnp_accessories_back':
            s.prop26 = 'ACCESSORIES';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:ACCESSORIES:DEFAULT:B&P - SELECT ACCESSORIES';
            CallSDotTL(s , true , 'BUILD & PRICE:ACCESSORIES:BACKWARD:BACK LINK' , 'o');
            break;
        case 'bnp_accessories_nextbtn':
            s.prop26 = 'ACCESSORIES';
            s.prop27 = 'FORWARD';
            s.prop37 = 'BUILD & PRICE:ACCESSORIES:DEFAULT:B&P - SELECT ACCESSORIES';
            CallSDotTL(s , true , 'BUILD & PRICE:COLORS:FORWARD:NEXT:SUMMARY LINK' , 'o');
            break;
        case 'bnp_summary_startover':
            s.prop26 = 'SUMMARY';
            s.prop27 = 'RESET';
            s.prop37 = 'BUILD & PRICE:SUMMARY:DEFAULT:B&P - SUMMARY';
            CallSDotTL(s , true , 'BUILD & PRICE:SUMMARY:RESET:START OVER LINK' , 'o');
            break;
        case 'bnp_confirm_startover':
            s.prop26 = 'QUOTE';
            s.prop27 = 'RESET';
            s.prop37 = 'BUILD & PRICE:QUOTE:DEFAULT:B&P - QUOTE REQUEST CONFIRMATION';
            CallSDotTL(s , true , 'BUILD & PRICE:QUOTE:RESET:START OVER LINK' , 'o');
            break;
        case 'bnp_2_hondatab':
            s.prop26 = 'MODEL';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:MODEL:DEFAULT:B&P - SELECT A MODEL';
            CallSDotTL(s , true , 'BUILD & PRICE:MODEL:BACKWARD:HONDA NAV LINK' , 'o');
            break;
        case 'bnp_2_colortab':
            s.prop26 = 'MODEL';
            s.prop27 = 'FORWARD';
            s.prop37 = 'BUILD & PRICE:MODEL:DEFAULT:B&P - SELECT A MODEL';
            CallSDotTL(s , true , 'BUILD & PRICE:MODEL:FORWARD:COLORS NAV LINK' , 'o');
            break;
        case 'bnp_3_hondatab':
            s.prop26 = 'COLORS';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:COLORS:DEFAULT:B&P - SELECT COLORS';
            CallSDotTL(s , true , 'BUILD & PRICE:COLORS:BACKWARD:HONDA NAV LINK' , 'o');
            break;
        case 'bnp_3_modeltab':
            s.prop26 = 'COLORS';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:COLORS:DEFAULT:B&P - SELECT COLORS';
            CallSDotTL(s , true , 'BUILD & PRICE:COLORS:BACKWARD:MODEL NAV LINK' , 'o');
            break;
        case 'bnp_3_acctab':
            s.prop26 = 'COLORS';
            s.prop27 = 'FORWARD';
            s.prop37 = 'BUILD & PRICE:COLORS:DEFAULT:B&P - SELECT COLORS';
            CallSDotTL(s , true , 'BUILD & PRICE:COLORS:FORWARD:ACCESSORIES NAV LINK' , 'o');
            break;
        case 'bnp_3_summarytab':
            s.prop26 = 'COLORS';
            s.prop27 = 'FORWARD';
            s.prop37 = 'BUILD & PRICE:COLORS:DEFAULT:B&P - SELECT COLORS';
            CallSDotTL(s , true , 'BUILD & PRICE:COLORS:FORWARD:SUMMARY NAV LINK' , 'o');
            break;
        case 'bnp_4_hondatab':
            s.prop26 = 'ACCESSORIES';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:ACCESSORIES:DEFAULT:B&P - SELECT ACCESSORIES';
            CallSDotTL(s , true , 'BUILD & PRICE:ACCESSORIES:BACKWARD:HONDA NAV LINK' , 'o');
            break;
        case 'bnp_4_modeltab':
            s.prop26 = 'ACCESSORIES';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:ACCESSORIES:DEFAULT:B&P - SELECT ACCESSORIES';
            CallSDotTL(s , true , 'BUILD & PRICE:ACCESSORIES:BACKWARD:MODEL NAV LINK' , 'o');
            break;
        case 'bnp_4_colortab':
            s.prop26 = 'MODEL';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:MODEL:DEFAULT:B&P - SELECT ACCESSORIES';
            CallSDotTL(s , true , 'BUILD & PRICE:MODEL:BACKWARD:COLORS NAV LINK' , 'o');
            break;
        case 'bnp_4_summarytab':
            s.prop26 = 'ACCESSORIES';
            s.prop27 = 'FORWARD';
            s.prop37 = 'BUILD & PRICE:ACCESSORIES:DEFAULT:B&P - SELECT ACCESSORIES';
            CallSDotTL(s , true , 'BUILD & PRICE:ACCESSORIES:FORWARD:SUMMARY NAV LINK' , 'o');
            break;
        case 'bnp_5_hondatab':
            s.prop26 = 'SUMMARY';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:SUMMARY:DEFAULT:B&P - SUMMARY';
            CallSDotTL(s , true , 'BUILD & PRICE:SUMMARY:BACKWARD:HONDA NAV LINK' , 'o');
            break;
        case 'bnp_5_modeltab':
            s.prop26 = 'SUMMARY';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:SUMMARY:DEFAULT:B&P - SUMMARY';
            CallSDotTL(s , true , 'BUILD & PRICE:SUMMARY:BACKWARD:MODEL NAV LINK' , 'o');
            break;
        case 'bnp_5_colortab':
            s.prop26 = 'SUMMARY';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:SUMMARY:DEFAULT:B&P - SUMMARY';
            CallSDotTL(s , true , 'BUILD & PRICE:SUMMARY:BACKWARD:COLORS NAV LINK' , 'o');
            break;
        case 'bnp_5_acctab':
            s.prop26 = 'SUMMARY';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:SUMMARY:DEFAULT:B&P - SUMMARY';
            CallSDotTL(s , true , 'BUILD & PRICE:SUMMARY:BACKWARD:ACCESSORIES NAV LINK' , 'o');
            break;
        case 'raq_trims_accordionback':
            s.prop26 = 'VEHICLE';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'RAQ:VEHICLE:HELP:RAQ - HELP ME SELECT A TRIM';
            CallSDotTL(s , true , 'RAQ:VEHICLE:BACKWARD:BACK LINK' , 'o');
            break;
        case 'bnp_trims_accordionback':
            s.prop26 = 'MODEL';
            s.prop27 = 'BACKWARD';
            s.prop37 = 'BUILD & PRICE:MODEL:DEFAULT:B&P - SELECT A MODEL';
            CallSDotTL(s , true , 'BUILD & PRICE:MODEL:BACKWARD:BACK LINK' , 'o');
            break;
        case 'bnp_trims_accordioncolors':
            s.prop26 = 'MODEL';
            s.prop27 = 'FORWARD';
            s.prop37 = 'BUILD & PRICE:FORWARD:DEFAULT:B&P - SELECT A MODEL';
            CallSDotTL(s , true , 'BUILD & PRICE:MODEL:FORWARD:NEXT:COLORS LINK' , 'o');
            break;
        case 'raq_trims_accordioncolors':
            s.prop26 = 'VEHICLE';
            s.prop27 = 'FORWARD';
            s.prop37 = 'RAQ:VEHICLE:HELP:RAQ - HELP ME SELECT A TRIM';
            CallSDotTL(s , true , 'RAQ:VEHICLE:FORWARD:NEXT:SELECT COLORS LINK' , 'o');
            break;

            

    }

}


//GENERAL
function calcMsrp(msrp, dhCost){
    var cleanMsrp = parseFloat(msrp.replace("$", "").replace(",", ""));
    var cleanDh = parseFloat(dhCost.replace("$", "").replace(",", ""));
    var sumStr = (cleanMsrp + cleanDh).toFixed(2).toString();
    var indexOfComma = sumStr.length - 6; //instead of sub-stringing forward 2 I'm working my way back from the hundredths place, in the off-chance the MSRP's over $100,000.00
    return "$" + sumStr.substr(0, indexOfComma) + "," + sumStr.substr(indexOfComma);
}

function removeDecimal(price){
    //return price.toString().replace(".00", "");
    var numStr = Math.round(parseFloat(price.replace("$", "").replace(",", ""))).toString();
    var indexOfComma = numStr.length - 3;
    if (numStr.length > 3){
        return "$" + numStr.substr(0, indexOfComma) + "," + numStr.substr(indexOfComma);
    }else{
        return "$" + numStr;
    }
}

// Process tracking information from querystring and page variables
function ProcessTrackingInformation(s) {

    var sModelName = $.getQueryString({id:"ModelName"});
    var sModelYear = $.getQueryString({id:"ModelYear"});
    var sModelID = $.getQueryString({id:"ModelID"});
    var sSelected = $.getQueryString({id:"Selected"});
    var sExtColor = $.getQueryString({id:"EColor"});
    var sIntColor = $.getQueryString({id:"IColor"});

    if (sModelName != 'null') {

        // Model    
        if (typeof(trimList) != 'undefined') {
            s.prop1 = trimList[0][3].toUpperCase();
        }

        // Year
        var sModelYear = sModelYear;
        if (sModelYear != 'null') {
            s.prop2 = sModelYear;
        }

        // Product
        if (s.prop1) {
            s.products = GetModelProductType(s.prop1) + ':' + s.prop1;
        }

    }

    if (sModelID != 'null') {

        // Transmission and trim name
        if (typeof(modelList) != 'undefined') {
            var stTransmissionName = modelList[0][4].toUpperCase();
            var stWheelDrive = '';
            
            stTransmissionName = ExtractTransmissionInfo(stTransmissionName , stWheelDrive);
            stWheelDrive = stTransmissionName.split('|')[1];
            stTransmissionName = stTransmissionName.split('|')[0];            

            s.prop5 = stWheelDrive + trimList[0][0].toUpperCase();
            s.prop33 = stTransmissionName;
        }
        
    }
            
    if ( (sExtColor != 'null') && (sIntColor != 'null') ) {

        if ( (typeof(exColorList) != 'undefined') && (typeof(inColorList) != 'undefined') ) {
            var stExteriorColorName = '';
            var stInteriorColorName = '';

            for (var iCount = 0; iCount< exColorList.length; iCount++) {
                if (exColorList[iCount][6] == $.getQueryString({id:"EColor"})) {
                    stExteriorColorName = exColorList[iCount][0].toUpperCase();
                }
            }
            for (var iCount = 0; iCount< inColorList.length; iCount++) {
                if (inColorList[iCount][1] == $.getQueryString({id:"IColor"})) {
                    stInteriorColorName = inColorList[iCount][0].toUpperCase();
                }
            }

            s.prop3 = stExteriorColorName;
            s.prop4 = stInteriorColorName;
        }
    }
            
    if (sSelected != 'null') {
        sSelected = sSelected.replace(/,/g , ':');
        if (sSelected != 'null') {
            s.prop7 = sSelected;
            s.prop6 = sSelected.split(':').length;
        }
    }

    return s;

}

// This function is being broken out so that it can be used by other functions.
// It returns a pipe delimited list of values since it has to return 2 pieces of information.
function ExtractTransmissionInfo(stTransmissionName , stWheelDrive) {

    if (stTransmissionName.indexOf('2WD') >= 0) {
        stWheelDrive = '2WD ';
        stTransmissionName = stTransmissionName.replace(/2WD/ , '');
    }
    if (stTransmissionName.indexOf('4WD') >= 0) {
        stWheelDrive = '4WD ';
        stTransmissionName = stTransmissionName.replace(/4WD/ , '');
    }
    
    return stTransmissionName + "|" + stWheelDrive;

}

// This is a generic function used to track click events through the build and price tool
function TrackBNPClick(s , sLinkName , prop26 , prop27 , sAdditionalLinkTrackVars , sLinkType) {

    if (sAdditionalLinkTrackVars != '') {
        sAdditionalLinkTrackVars = ',' + sAdditionalLinkTrackVars;
    }
    
    if (!sLinkType) {
        sLinkType = 'o'
    }

    s.linkTrackVars = 'prop26,prop27,prop37,eVar26,eVar27' + sAdditionalLinkTrackVars;
    s.prop26 = prop26;
    s.prop27 = prop27;
    CallSDotTL(s , true , sLinkName , sLinkType);

}

function ShowCurrentOffer(modelName, modelYear, modelId, trimName, offerID){
    modelId = (modelId == null) ? "" : modelId;
    trimName = (trimName == null) ? "" : trimName;
    if ( typeof(tb_show) === 'function') {
        tb_show("" , "/tools/current-offers-pop-up.aspx?modelName=" + modelName + "&modelYear=" + modelYear + "&modelId=" + modelId + "&trimName=" + trimName + "&offerID=" + offerID + "&width=740&height=550&modal=true&TB_iframe=true", "");
    } else {
        window.open("/tools/current-offers-pop-up.aspx?modelName=" + modelName + "&modelYear=" + modelYear + "&modelId=" + modelId + "&trimName=" + trimName + "&offerID=" + offerID,"Current_Offers","menubar=no,width=740,height=550,toolbar=no");
    }
}



function FixPNG(){var sAppVersion=navigator.appVersion;if(sAppVersion.indexOf('MSIE')>0){var sVersion=parseFloat(sAppVersion.split('MSIE')[1]);if(sVersion>=7){return;}}else{return;}
var aItems=document.getElementsByTagName('*');for(var iCount=0;iCount<aItems.length;iCount++){var oImg=aItems[iCount];if((oImg.src)&&(oImg.src.toLowerCase().indexOf('.png')>0)){var prevStyle='';var strNewHTML='';var imgID=(oImg.id)?'id="'+oImg.id+'" ':'';var imgClass=(oImg.className)?'class="'+oImg.className+'" ':'';var imgTitle=(oImg.title)?'title="'+oImg.title+'" ':'';var imgAlt=(oImg.alt)?'alt="'+oImg.alt+'" ':'';var imgAlign=(oImg.align)?'float:'+oImg.align+';':'';var imgHand=(oImg.href)?'cursor:hand;':'';var imgStyle='display:inline-block;'+oImg.style.cssText;if(oImg.style.border){prevStyle+='border:'+oImg.style.border+';';oImg.style.border='';}
if(oImg.style.padding){prevStyle+='padding:'+oImg.style.padding+';';oImg.style.padding='';}
if(oImg.style.margin){prevStyle+='margin:'+oImg.style.margin+';';oImg.style.margin='';}
var imgStyle=(oImg.style.cssText);var strNewHTML='<span '+imgID+imgClass+imgTitle+imgAlt;strNewHTML+='style="position:relative;white-space:pre-line;display:inline-block;background:transparent;'+imgAlign+imgHand;strNewHTML+='width:'+oImg.width+'px;'+'height:'+oImg.height+'px;';strNewHTML+='filter:progid:DXImageTransform.Microsoft.AlphaImageLoader'+'(src=\''+oImg.src+'\', sizingMethod=\'scale\');';strNewHTML+=imgStyle+'"></span>';if(prevStyle!=''){strNewHTML='<span style="position:relative;display:inline-block;'+prevStyle+imgHand+'width:'+oImg.width+'px;'+'height:'+oImg.height+'px;'+'">'+strNewHTML+'</span>';}
oImg.outerHTML=strNewHTML;}}
try{var CSSRules;for(var i=0;i<document.styleSheets.length;i++){(document.styleSheets[0].cssRules)?CSSRules='cssRules':CSSRules='rules';for(var j=0;j<document.styleSheets[i][CSSRules].length;j++){if((document.styleSheets[i][CSSRules][j].style['backgroundImage'])&&(document.styleSheets[i][CSSRules][j].style['backgroundImage']!='')&&(document.styleSheets[i][CSSRules][j].style['backgroundImage']!='none')&&(document.styleSheets[i][CSSRules][j].style['backgroundImage'].toLowerCase().indexOf('.png')>0)&&(!document.styleSheets[i][CSSRules][j].style['progid'])){var sOriginalBG=document.styleSheets[i][CSSRules][j].style['backgroundImage'];sOriginalBG=sOriginalBG.replace('url(','');sOriginalBG=sOriginalBG.replace(')','');}}}}catch(err){}
var aItems=document.getElementsByTagName('*');for(var iCount=0;iCount<aItems.length;iCount++){var oItem=aItems[iCount];if(oItem.style.backgroundImage){if(oItem.style.backgroundImage.toLowerCase().indexOf('.png')>0){var sOriginalBG=oItem.style.backgroundImage;sOriginalBG=sOriginalBG.replace('url(','');sOriginalBG=sOriginalBG.replace(')','');document.getElementById(oItem.id).style.backgroundImage='none';document.getElementById(oItem.id).runtimeStyle.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+sOriginalBG+"',sizingMethod='scale')";}}}}

function ClearDefaultText(FormElement){
    if(FormElement){
        if(FormElement.title){
            if(FormElement.title==FormElement.value) FormElement.value="";
        }
    }
}

function CloseLeaveSiteDialog(){
    var oDiv=document.getElementById("GlobalLeaveSiteLayer");
    if(oDiv){
        oDiv.style.display="none";
    }
}

function LeaveSite(sUrl){
    var oDiv=document.getElementById("GlobalLeaveSiteLayer");
    if(!oDiv){
        var oDiv=document.createElement("div");
        oDiv.id="GlobalLeaveSiteLayer";
        oDiv.style.display="none";
        document.body.appendChild(oDiv);
    }
    var sHtml="<div id=\"GlobalLeaveSiteLayerTop\">" +
            "<div id=\"GlobalLeaveSiteLayerClose\"><a href=\"javascript:CloseLeaveSiteDialog()\"><img src=\"/images/leave-site/leavesite-close.gif\" width=\"67\" height=\"16\" /></a></div>" +
        "</div>" +
        "<div id=\"GlobalLeaveSiteLayerContent\">&nbsp;" +
            "<div id=\"GlobalLeaveSiteLayerText\">" +
                "<b>You are leaving the Honda Automobile Web Site.</b>" +
                "<br /><br />" +
                "The following link is an independent site.<br />" +
                "American Honda Motor Co. Inc., is not responsible for the content presented by any independent Web site, including advertising claims, special offers, illustrations, names or endorsements." +
                "<br /><br />" +
                "Click the link to continue:<br />" +
                "<div class=\"DottedLink\"><a href=\"" + sUrl + "\" target=\"_blank\" onclick=\"CloseLeaveSiteDialog()\">" + sUrl + "</a></div>" + 
                "<br /><br />" +
                "<a href=\"javascript:CloseLeaveSiteDialog()\" onmouseover=\"SwitchImg('GlobalLeaveSiteCancelButton', '/images/_global/buttons/btn-cancel-over.gif')\" onmouseout=\"SwitchImg('GlobalLeaveSiteCancelButton', '/images/_global/buttons/btn-cancel-off.gif')\"><img src=\"/images/_global/buttons/btn-cancel-off.gif\" id=\"GlobalLeaveSiteCancelButton\" width=\"86\" height=\"21\" /></a>" +
            "</div>" +
        "</div>" +
        "<div id=\"GlobalLeaveSiteLayerBottom\"><img src=\"/images/leave-site/leavesite-bottom.gif\" width=\"569\" height=\"14\" /></div>";
    oDiv.innerHTML=sHtml;
    var x=0;
    var y=0;
    var ScrollX=0;
    var ScrollY=0;
    if( typeof( window.innerWidth ) == 'number' ) {
        x = window.innerWidth;
        y = window.innerHeight;
      } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
        x = document.documentElement.clientWidth;
        y = document.documentElement.clientHeight;
      } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
        x = document.body.clientWidth;
        y = document.body.clientHeight;
      }
      if( typeof( window.pageYOffset ) == 'number' ) {
        ScrollY = window.pageYOffset;
        ScrollX = window.pageXOffset;
      } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
        ScrollY = document.body.scrollTop;
        ScrollX = document.body.scrollLeft;
      } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
        ScrollY = document.documentElement.scrollTop;
        ScrollX = document.documentElement.scrollLeft;
      }
      oDiv.style.top=(y/2)-(288/2)+ScrollY;
      oDiv.style.left=(x/2)-(569/2)+ScrollX;
      oDiv.style.display="";
    return false;
}

function OnLoadAppend(FunctionCall){
    OnLoadFunctions[OnLoadFunctions.length]=FunctionCall;
}
function OnLoadExecute(){
    for(var i=0; i<OnLoadFunctions.length; i++){
        eval(OnLoadFunctions[i]);
    }
}

function ReturnToLastPage(){
    var sUrl=GetCookie("CurrentURL");
    if(sUrl!="" && sUrl!=null){
        top.location.href=sUrl;
    }else{
        // Redirect user to home page in http since this page may be in https
        sURL = 'http://' + document.location.host + '/';
        top.location.href = sURL;
    }
}

function SwitchImg(ImageName, ImageSrc){
    if(document.getElementById){
        var ImageObj=document.getElementById(ImageName);
        if(ImageObj){
            ImageObj.src=ImageSrc;
        }
    }
}

function SetCookie(name, value , oDate) {
    document.cookie = name + "=" + escape( value ) + ";path=/" +
        ( (oDate) ?  ";expires=" + oDate.toString() : "" );
}

function GetCookie(name) {
  var cookie=document.cookie;
  var start=cookie.indexOf(name+"=");
  if(start>=0) 
  {
  	var end = document.cookie.indexOf(";", start);
    if (end == -1) end = cookie.length;
  	return unescape(cookie.substring(start + name.length+1,end));
  }
  else return null;
}

// This function will allow a value to be added/replaced in the "CurrentURL" cookie asynchronously
function SetReturnURLParam(name,value)
{
    var rurl=GetCookie("CurrentURL");
    if(rurl.indexOf("?")>0)
	{
		var urlpart=rurl.split("?")[0];
		var nvarray=rurl.split("?")[1].split("&");
		var finalqs="";
		var found=false;
		for(i=0;i<nvarray.length;i++)
		{
			if(nvarray[i].indexOf(name+"=")==0)
			{
				nvarray[i]=name+"="+value;
				found=true;
			}
			if(nvarray[i].length>0) finalqs+=nvarray[i]+"&";
		}
		if(!found) finalqs+=name+"="+value;
		else finalqs=finalqs.substring(0,finalqs.length-1);
		rurl=urlpart+"?"+finalqs;
	}
    else rurl=rurl+"?"+name+"="+value;

    if(!OverrideCookie) SetCookie("CurrentURL",rurl);
    PageURL = rurl;
}

var OnLoadFunctions=new Array();
window.onload=OnLoadExecute;

// Set the "CurrnetURL" cookie to the page's current URL
if(typeof(OverrideCookie)=="undefined") OverrideCookie=false;
if(!OverrideCookie) SetCookie("CurrentURL" , location.href);
var PageURL = location.href;


// In a lot of places, the Model Name is concatenated with the Trim Name
// (e.g. Accord Sedan LX). In some places, the Model Name is repeated in the
// trim name (e.g. Accord Hybrid Hybrid). This function will look for words in the
// Model Name within the Trim Name and remove them (so Accord Hybrid Hybrid becomes
// Accord Hybrid).
function DedupeModelTrim(sModelName , sTrimName) {
 
    // Split ModelName into individual words
    var aModelWords = sModelName.split(" ");
    
    // Split TrimName into individual words
    var aTrimWords = sTrimName.split(" ");
    
    // Loop through all words in the trim name and see if they match any words in the model name.
    // If they do, remove them from the trim name
    for (var iTrimCount = 0; iTrimCount < aTrimWords.length; iTrimCount++) {
        for (var iModelCount = 0; iModelCount < aModelWords.length; iModelCount++) {
            if (aTrimWords[iTrimCount].toLowerCase() == aModelWords[iModelCount].toLowerCase()) {
                aTrimWords[iTrimCount] = '';
            }
        }
    }
    
    sTrimName = aTrimWords.join(" ");
   

 
    return sTrimName;
}


function GetQueryStringParamValue(parameter) {
		
		var sLocation = location.href;
		var value;
		var index = sLocation.indexOf(parameter + '=');
		
		if ( index < 0){
			value = "";
		}
		else{
			value = sLocation.substring(index+parameter.length+1, sLocation.length);
			
			if ( value.indexOf('&') > -1){
				value = value.substring(0, value.indexOf('&'));
			}
		}
		
		return value;
}

function TagRand() {
    return Math.floor(Math.random()*60000);
}

var mboxCopyright = "&copy; 2003-2009. Omniture, Inc. All rights reserved.";mboxUrlBuilder = function(a, b) { this.a = a; this.b = b; this.c = new Array(); this.d = function(e) { return e; }; this.f = null;};mboxUrlBuilder.prototype.addParameter = function(g, h) { var i = new RegExp('(\'|")'); if (i.exec(g)) { throw "Parameter '" + g + "' contains invalid characters"; } for (var j = 0; j < this.c.length; j++) { var k = this.c[j]; if (k.name == g) { k.value = h; return this; } } var l = new Object(); l.name = g; l.value = h; this.c[this.c.length] = l; return this;};mboxUrlBuilder.prototype.addParameters = function(c) { if (!c) { return this; } for (var j = 0; j < c.length; j++) { var m = c[j].indexOf('='); if (m == -1 || m == 0) { continue; } this.addParameter(c[j].substring(0, m), c[j].substring(m + 1, c[j].length)); } return this;};mboxUrlBuilder.prototype.setServerType = function(n) { this.o = n;};mboxUrlBuilder.prototype.setBasePath = function(f) { this.f = f;};mboxUrlBuilder.prototype.setUrlProcessAction = function(p) { this.d = p;};mboxUrlBuilder.prototype.buildUrl = function() { var q = this.f ? this.f : '/m2/' + this.b + '/mbox/' + this.o; var r = document.location.protocol == 'file:' ? 'http:' : document.location.protocol; var e = r + "//" + this.a + q; var s = e.indexOf('?') != -1 ? '&' : '?'; for (var j = 0; j < this.c.length; j++) { var k = this.c[j]; e += s + encodeURIComponent(k.name) + '=' + encodeURIComponent(k.value); s = '&'; } return this.t(this.d(e));};mboxUrlBuilder.prototype.getParameters = function() { return this.c;};mboxUrlBuilder.prototype.setParameters = function(c) { this.c = c;};mboxUrlBuilder.prototype.clone = function() { var u = new mboxUrlBuilder(this.a, this.b); u.setServerType(this.o); u.setBasePath(this.f); u.setUrlProcessAction(this.d); for (var j = 0; j < this.c.length; j++) { u.addParameter(this.c[j].name, this.c[j].value); } return u;};mboxUrlBuilder.prototype.t = function(v) { return v.replace(/\"/g, '&quot;').replace(/>/g, '&gt;');};mboxStandardFetcher = function() { };mboxStandardFetcher.prototype.getType = function() { return 'standard';};mboxStandardFetcher.prototype.fetch = function(w) { w.setServerType(this.getType()); document.write('<' + 'scr' + 'ipt src="' + w.buildUrl() + '" language="JavaScript"><' + '\/scr' + 'ipt>');};mboxStandardFetcher.prototype.cancel = function() { };mboxAjaxFetcher = function() { };mboxAjaxFetcher.prototype.getType = function() { return 'ajax';};mboxAjaxFetcher.prototype.fetch = function(w) { w.setServerType(this.getType()); var e = w.buildUrl(); this.x = document.createElement('script'); this.x.src = e; document.body.appendChild(this.x);};mboxAjaxFetcher.prototype.cancel = function() { };mboxMap = function() { this.y = new Object(); this.z = new Array();};mboxMap.prototype.put = function(A, h) { if (!this.y[A]) { this.z[this.z.length] = A; } this.y[A] = h;};mboxMap.prototype.get = function(A) { return this.y[A];};mboxMap.prototype.remove = function(A) { this.y[A] = undefined;};mboxMap.prototype.each = function(p) { for (var j = 0; j < this.z.length; j++ ) { var A = this.z[j]; var h = this.y[A]; if (h) { p(A, h); } }};mboxFactory = function(B, b, C) { this.D = false; this.B = B; this.C = C; this.E = new mboxList(); mboxFactories.put(C, this); this.F = typeof document.createElement('div').replaceChild != 'undefined' && (function() { return true; })() && typeof document.getElementById != 'undefined' && typeof (window.attachEvent || document.addEventListener || window.addEventListener) != 'undefined' && typeof encodeURIComponent != 'undefined'; this.G = this.F && mboxGetPageParameter('mboxDisable') == null; var H = C == 'default'; this.I = new mboxCookieManager( 'mbox' + (H ? '' : ('-' + C)), (function() { return mboxCookiePageDomain(); })()); this.G = this.G && this.I.isEnabled() && (this.I.getCookie('disable') == null); if (this.isAdmin()) { this.enable(); } this.J = mboxGenerateId(); this.K = new mboxSession(this.J, 'mboxSession', 'session', 31 * 60, this.I); this.L = new mboxPC('PC', 1209600, this.I); this.w = new mboxUrlBuilder(B, b); this.M(this.w, H); this.N = new Date().getTime(); this.O = this.N; var P = this; this.addOnLoad(function() { P.O = new Date().getTime(); }); if (this.F) { this.addOnLoad(function() { P.D = true; P.getMboxes().each(function(Q) { Q.setFetcher(new mboxAjaxFetcher()); Q.finalize(); }); }); this.limitTraffic(100, 10368000); if (this.G) { this.R(); this.S = new mboxSignaler(function(T, c) { return P.create(T, c); }, this.I); } }};mboxFactory.prototype.isEnabled = function() { return this.G;};mboxFactory.prototype.getDisableReason = function() { return this.I.getCookie('disable');};mboxFactory.prototype.isSupported = function() { return this.F;};mboxFactory.prototype.disable = function(U, V) { if (typeof U == 'undefined') { U = 60 * 60; } if (typeof V == 'undefined') { V = 'unspecified'; } if (!this.isAdmin()) { this.G = false; this.I.setCookie('disable', V, U); }};mboxFactory.prototype.enable = function() { this.G = true; this.I.deleteCookie('disable');};mboxFactory.prototype.isAdmin = function() { return document.location.href.indexOf('mboxEnv') != -1;};mboxFactory.prototype.limitTraffic = function(W, U) {};mboxFactory.prototype.addOnLoad = function(p) { if (window.addEventListener) { window.addEventListener('load', p, false); } else if (document.addEventListener) { document.addEventListener('load', p, false); } else if (document.attachEvent) { window.attachEvent('onload', p); }};mboxFactory.prototype.getEllapsedTime = function() { return this.O - this.N;};mboxFactory.prototype.getEllapsedTimeUntil = function(X) { return X - this.N;};mboxFactory.prototype.getMboxes = function() { return this.E;};mboxFactory.prototype.get = function(T, Y) { return this.E.get(T).getById(Y || 0);};mboxFactory.prototype.update = function(T, c) { if (!this.isEnabled()) { return; } if (this.E.get(T).length() == 0) { throw "Mbox " + T + " is not defined"; } this.E.get(T).each(function(Q) { Q.getUrlBuilder() .addParameter('mboxPage', mboxGenerateId()); Q.load(c); });};mboxFactory.prototype.create = function( T, c, Z) { if (!this.isSupported()) { return null; } var e = this.w.clone(); e.addParameter('mboxCount', this.E.length() + 1); e.addParameters(c); var Y = this.E.get(T).length(); var _ = this.C + '-' + T + '-' + Y; var ab; if (Z) { ab = new mboxLocatorNode(Z); } else { if (this.D) { throw 'The page has already been loaded, can\'t write marker'; } ab = new mboxLocatorDefault(_); } try { var P = this; var bb = 'mboxImported-' + _; var Q = new mbox(T, Y, e, ab, bb); if (this.G) { Q.setFetcher(this.D ? new mboxAjaxFetcher() : new mboxStandardFetcher()); } Q.setOnError(function(cb, n) { Q.setMessage(cb); Q.activate(); if (!Q.isActivated()) { P.disable(60 * 60, cb); window.location.reload(false); } }); this.E.add(Q); } catch (db) { this.disable(); throw 'Failed creating mbox "' + T + '", the error was: ' + db; } var eb = new Date(); e.addParameter('mboxTime', eb.getTime() - (eb.getTimezoneOffset() * 60000)); return Q;};mboxFactory.prototype.getCookieManager = function() { return this.I;};mboxFactory.prototype.getPageId = function() { return this.J;};mboxFactory.prototype.getPCId = function() { return this.L;};mboxFactory.prototype.getSessionId = function() { return this.K;};mboxFactory.prototype.getSignaler = function() { return this.S;};mboxFactory.prototype.getUrlBuilder = function() { return this.w;};mboxFactory.prototype.M = function(e, H) { e.addParameter('mboxHost', document.location.hostname) .addParameter('mboxSession', this.K.getId()); if (!H) { e.addParameter('mboxFactoryId', this.C); } if (this.L.getId() != null) { e.addParameter('mboxPC', this.L.getId()); } e.addParameter('mboxPage', this.J); e.setUrlProcessAction(function(e) { e += '&mboxURL=' + encodeURIComponent(document.location); var fb = encodeURIComponent(document.referrer); if (e.length + fb.length < 2000) { e += '&mboxReferrer=' + fb; } e += '&mboxVersion=' + mboxVersion; return e; });};mboxFactory.prototype.gb = function() { return "";};mboxFactory.prototype.R = function() { document.write('<style>.' + 'mboxDefault' + ' { visibility:hidden; }</style>');};mboxFactory.prototype.isDomLoaded = function() { return this.D;};mboxSignaler = function(hb, I) { this.I = I; var ib = I.getCookieNames('signal-'); for (var j = 0; j < ib.length; j++) { var jb = ib[j]; var kb = I.getCookie(jb).split('&'); var Q = hb(kb[0], kb); Q.load(); I.deleteCookie(jb); }};mboxSignaler.prototype.signal = function(lb, T ) { this.I.setCookie('signal-' + lb, mboxShiftArray(arguments).join('&'), 45 * 60);};mboxList = function() { this.E = new Array();};mboxList.prototype.add = function(Q) { if (Q != null) { this.E[this.E.length] = Q; }};mboxList.prototype.get = function(T) { var mb = new mboxList(); for (var j = 0; j < this.E.length; j++) { var Q = this.E[j]; if (Q.getName() == T) { mb.add(Q); } } return mb;};mboxList.prototype.getById = function(nb) { return this.E[nb];};mboxList.prototype.length = function() { return this.E.length;};mboxList.prototype.each = function(p) { if (typeof p != 'function') { throw 'Action must be a function, was: ' + typeof(p); } for (var j = 0; j < this.E.length; j++) { p(this.E[j]); }};mboxLocatorDefault = function(g) { this.g = 'mboxMarker-' + g; document.write('<div id="' + this.g + '" style="visibility:hidden;display:none">&nbsp;</div>');};mboxLocatorDefault.prototype.locate = function() { var ob = document.getElementById(this.g); while (ob != null) { if (ob.nodeType == 1) { if (ob.className == 'mboxDefault') { return ob; } } ob = ob.previousSibling; } return null;};mboxLocatorDefault.prototype.force = function() { var pb = document.createElement('div'); pb.className = 'mboxDefault'; var qb = document.getElementById(this.g); qb.parentNode.insertBefore(pb, qb); return pb;};mboxLocatorNode = function(rb) { this.ob = rb;};mboxLocatorNode.prototype.locate = function() { return typeof this.ob == 'string' ? document.getElementById(this.ob) : this.ob;};mboxLocatorNode.prototype.force = function() { return null;};mboxCreate = function(T ) { var Q = mboxFactoryDefault.create( T, mboxShiftArray(arguments)); if (Q) { Q.load(); } return Q;};mboxDefine = function(Z, T ) { var Q = mboxFactoryDefault.create(T, mboxShiftArray(mboxShiftArray(arguments)), Z); return Q;};mboxUpdate = function(T ) { mboxFactoryDefault.update(T, mboxShiftArray(arguments));};mbox = function(g, sb, w, tb, bb) { this.ub = null; this.vb = 0; this.ab = tb; this.bb = bb; this.wb = null; this.xb = new mboxOfferContent(); this.pb = null; this.w = w; this.message = ''; this.yb = new Object(); this.zb = 0; this.sb = sb; this.g = g; this.Ab(); w.addParameter('mbox', g) .addParameter('mboxId', sb); this.Bb = function() {}; this.Cb = function() {}; this.Db = null;};mbox.prototype.getId = function() { return this.sb;};mbox.prototype.Ab = function() { if (this.g.length > 250) { throw "Mbox Name " + this.g + " exceeds max length of " + "250 characters."; } else if (this.g.match(/^\s+|\s+$/g)) { throw "Mbox Name " + this.g + " has leading/trailing whitespace(s)."; }};mbox.prototype.getName = function() { return this.g;};mbox.prototype.getParameters = function() { var c = this.w.getParameters(); var mb = new Array(); for (var j = 0; j < c.length; j++) { if (c[j].name.indexOf('mbox') != 0) { mb[mb.length] = c[j].name + '=' + c[j].value; } } return mb;};mbox.prototype.setOnLoad = function(p) { this.Cb = p; return this;};mbox.prototype.setMessage = function(cb) { this.message = cb; return this;};mbox.prototype.setOnError = function(Bb) { this.Bb = Bb; return this;};mbox.prototype.setFetcher = function(Eb) { if (this.wb) { this.wb.cancel(); } this.wb = Eb; return this;};mbox.prototype.getFetcher = function() { return this.wb;};mbox.prototype.load = function(c) { if (this.wb == null) { return this; } this.setEventTime("load.start"); this.cancelTimeout(); this.vb = 0; var w = (c && c.length > 0) ? this.w.clone().addParameters(c) : this.w; this.wb.fetch(w); var P = this; this.Fb = setTimeout(function() { P.Bb('browser timeout', P.wb.getType()); }, 15000); this.setEventTime("load.end"); return this;};mbox.prototype.loaded = function() { this.cancelTimeout(); if (!this.activate()) { var P = this; setTimeout(function() { P.loaded(); }, 100); }};mbox.prototype.activate = function() { if (this.vb) { return this.vb; } this.setEventTime('activate' + ++this.zb + '.start'); if (this.show()) { this.cancelTimeout(); this.vb = 1; } this.setEventTime('activate' + this.zb + '.end'); return this.vb;};mbox.prototype.isActivated = function() { return this.vb;};mbox.prototype.setOffer = function(xb) { if (xb && xb.show && xb.setOnLoad) { this.xb = xb; } else { throw 'Invalid offer'; } return this;};mbox.prototype.getOffer = function() { return this.xb;};mbox.prototype.show = function() { this.setEventTime('show.start'); var mb = this.xb.show(this); this.setEventTime(mb == 1 ? "show.end.ok" : "show.end"); return mb;};mbox.prototype.showContent = function(Gb) { if (Gb == null) { return 0; } if (this.pb == null || !this.pb.parentNode) { this.pb = this.getDefaultDiv(); if (this.pb == null) { return 0; } } if (this.pb != Gb) { this.Hb(this.pb); this.pb.parentNode.replaceChild(Gb, this.pb); this.pb = Gb; } this.Ib(Gb); this.Cb(); return 1;};mbox.prototype.hide = function() { this.setEventTime('hide.start'); var mb = this.showContent(this.getDefaultDiv()); this.setEventTime(mb == 1 ? 'hide.end.ok' : 'hide.end.fail'); return mb;};mbox.prototype.finalize = function() { this.setEventTime('finalize.start'); this.cancelTimeout(); if (this.getDefaultDiv() == null) { if (this.ab.force() != null) { this.setMessage('No default content, an empty one has been added'); } else { this.setMessage('Unable to locate mbox'); } } if (!this.activate()) { this.hide(); this.setEventTime('finalize.end.hide'); } this.setEventTime('finalize.end.ok');};mbox.prototype.cancelTimeout = function() { if (this.Fb) { clearTimeout(this.Fb); } if (this.wb != null) { this.wb.cancel(); }};mbox.prototype.getDiv = function() { return this.pb;};mbox.prototype.getDefaultDiv = function() { if (this.Db == null) { this.Db = this.ab.locate(); } return this.Db;};mbox.prototype.setEventTime = function(Jb) { this.yb[Jb] = (new Date()).getTime();};mbox.prototype.getEventTimes = function() { return this.yb;};mbox.prototype.getImportName = function() { return this.bb;};mbox.prototype.getURL = function() { return this.w.buildUrl();};mbox.prototype.getUrlBuilder = function() { return this.w;};mbox.prototype.Kb = function(pb) { return pb.style.display != 'none';};mbox.prototype.Ib = function(pb) { this.Lb(pb, true);};mbox.prototype.Hb = function(pb) { this.Lb(pb, false);};mbox.prototype.Lb = function(pb, Mb) { pb.style.visibility = Mb ? "visible" : "hidden"; pb.style.display = Mb ? "block" : "none";};mboxOfferContent = function() { this.Cb = function() {};};mboxOfferContent.prototype.show = function(Q) { var mb = Q.showContent(document.getElementById(Q.getImportName())); if (mb == 1) { this.Cb(); } return mb;};mboxOfferContent.prototype.setOnLoad = function(Cb) { this.Cb = Cb;};mboxOfferAjax = function(Gb) { this.Gb = Gb; this.Cb = function() {};};mboxOfferAjax.prototype.setOnLoad = function(Cb) { this.Cb = Cb;};mboxOfferAjax.prototype.show = function(Q) { var Nb = document.createElement('div'); Nb.id = Q.getImportName(); Nb.innerHTML = this.Gb; var mb = Q.showContent(Nb); if (mb == 1) { this.Cb(); } return mb;};mboxOfferDefault = function() { this.Cb = function() {};};mboxOfferDefault.prototype.setOnLoad = function(Cb) { this.Cb = Cb;};mboxOfferDefault.prototype.show = function(Q) { var mb = Q.hide(); if (mb == 1) { this.Cb(); } return mb;};mboxCookieManager = function mboxCookieManager(g, Ob) { this.g = g; this.Ob = Ob == '' || Ob.indexOf('.') == -1 ? '' : '; domain=' + Ob; this.Pb = new mboxMap(); this.loadCookies();};mboxCookieManager.prototype.isEnabled = function() { this.setCookie('check', 'true', 60); this.loadCookies(); return this.getCookie('check') == 'true';};mboxCookieManager.prototype.setCookie = function(g, h, U) { if (typeof g != 'undefined' && typeof h != 'undefined' && typeof U != 'undefined') { var Qb = new Object(); Qb.name = g; Qb.value = escape(h); Qb.expireOn = Math.ceil(U + new Date().getTime() / 1000); this.Pb.put(g, Qb); this.saveCookies(); }};mboxCookieManager.prototype.getCookie = function(g) { var Qb = this.Pb.get(g); return Qb ? unescape(Qb.value) : null;};mboxCookieManager.prototype.deleteCookie = function(g) { this.Pb.remove(g); this.saveCookies();};mboxCookieManager.prototype.getCookieNames = function(Rb) { var Sb = new Array(); this.Pb.each(function(g, Qb) { if (g.indexOf(Rb) == 0) { Sb[Sb.length] = g; } }); return Sb;};mboxCookieManager.prototype.saveCookies = function() { var Tb = new Array(); var Ub = 0; this.Pb.each(function(g, Qb) { Tb[Tb.length] = g + '#' + Qb.value + '#' + Qb.expireOn; if (Ub < Qb.expireOn) { Ub = Qb.expireOn; } }); var Vb = new Date(Ub * 1000); document.cookie = this.g + '=' + Tb.join('|') + '; expires=' + Vb.toGMTString() + '; path=/' + this.Ob;};mboxCookieManager.prototype.loadCookies = function() { this.Pb = new mboxMap(); var Wb = document.cookie.indexOf(this.g + '='); if (Wb != -1) { var Xb = document.cookie.indexOf(';', Wb); if (Xb == -1) { Xb = document.cookie.indexOf(',', Wb); if (Xb == -1) { Xb = document.cookie.length; } } var Yb = document.cookie.substring( Wb + this.g.length + 1, Xb).split('|'); var Zb = Math.ceil(new Date().getTime() / 1000); for (var j = 0; j < Yb.length; j++) { var Qb = Yb[j].split('#'); if (Zb <= Qb[2]) { var _b = new Object(); _b.name = Qb[0]; _b.value = Qb[1]; _b.expireOn = Qb[2]; this.Pb.put(_b.name, _b); } } }};mboxSession = function(ac, bc, jb, cc, I) { this.bc = bc; this.jb = jb; this.cc = cc; this.I = I; this.dc = false; this.sb = typeof mboxForceSessionId != 'undefined' ? mboxForceSessionId : mboxGetPageParameter(this.bc); if (this.sb == null || this.sb.length == 0) { this.sb = I.getCookie(jb); if (this.sb == null || this.sb.length == 0) { this.sb = ac; this.dc = true; } } I.setCookie(jb, this.sb, cc);};mboxSession.prototype.getId = function() { return this.sb;};mboxSession.prototype.forceId = function(ec) { this.sb = ec; this.I.setCookie(this.jb, this.sb, this.cc);};mboxPC = function(jb, cc, I) { this.jb = jb; this.cc = cc; this.I = I; this.sb = typeof mboxForcePCId != 'undefined' ? mboxForcePCId : I.getCookie(jb); if (this.sb != null) { I.setCookie(jb, this.sb, cc); }};mboxPC.prototype.getId = function() { return this.sb;};mboxPC.prototype.forceId = function(ec) { if (this.sb != ec) { this.sb = ec; this.I.setCookie(this.jb, this.sb, this.cc); return true; } return false;};mboxGetPageParameter = function(g) { var mb = null; var fc = new RegExp(g + "=([^\&]*)"); var gc = fc.exec(document.location); if (gc != null && gc.length >= 2) { mb = gc[1]; } return mb;};mboxSetCookie = function(g, h, U) { return mboxFactoryDefault.getCookieManager().setCookie(g, h, U);};mboxGetCookie = function(g) { return mboxFactoryDefault.getCookieManager().getCookie(g);};mboxCookiePageDomain = function() { var Ob = (/([^:]*)(:[0-9]{0,5})?/).exec(document.location.host)[1]; var hc = /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/; if (!hc.exec(Ob)) { var ic = (/([^\.]+\.[^\.]{3}|[^\.]+\.[^\.]+\.[^\.]{2})$/).exec(Ob); if (ic) { Ob = ic[0]; } } return Ob ? Ob: "";};mboxShiftArray = function(jc) { var mb = new Array(); for (var j = 1; j < jc.length; j++) { mb[mb.length] = jc[j]; } return mb;};mboxGenerateId = function() { return (new Date()).getTime() + "-" + Math.floor(Math.random() * 999999);};if (typeof mboxVersion == 'undefined') { var mboxVersion = 38; var mboxFactories = new mboxMap(); var mboxFactoryDefault = new mboxFactory('honda.tt.omtrdc.net', 'honda', 'default');};if (mboxGetPageParameter("mboxDebug") != null || mboxFactoryDefault.getCookieManager() .getCookie("debug") != null) { setTimeout(function() { if (typeof mboxDebugLoaded == 'undefined') { alert('Could not load the remote debug.\nPlease check your connection' + ' to Test&amp;Target servers'); } }, 60*60); document.write('<' + 'scr' + 'ipt language="Javascript1.2" src=' + '"http://admin12.testandtarget.omniture.com/admin/mbox/mbox_debug.jsp?mboxServerHost=honda.tt.omtrdc.net' + '&clientCode=honda"><' + '\/scr' + 'ipt>');};mboxScPluginFetcher = function(b, kc) { this.b = b; this.kc = kc;};mboxScPluginFetcher.prototype.lc = function(w) { w.setBasePath('/m2/' + this.b + '/sc/standard'); this.mc(w); var e = w.buildUrl(); e += '&scPluginVersion=1'; return e;};mboxScPluginFetcher.prototype.mc = function(w) { var nc = [ "dynamicVariablePrefix","visitorID","vmk","ppu","charSet", "visitorNamespace","cookieDomainPeriods","cookieLifetime","pageName", "currencyCode","variableProvider","channel","server", "pageType","transactionID","purchaseID","campaign","state","zip","events", "products","linkName","linkType","resolution","colorDepth", "javascriptVersion","javaEnabled","cookiesEnabled","browserWidth", "browserHeight","connectionType","homepage","pe","pev1","pev2","pev3", "visitorSampling","visitorSamplingGroup","dynamicAccountSelection", "dynamicAccountList","dynamicAccountMatch","trackDownloadLinks", "trackExternalLinks","trackInlineStats","linkLeaveQueryString", "linkDownloadFileTypes","linkExternalFilters","linkInternalFilters", "linkTrackVars","linkTrackEvents","linkNames","lnk","eo" ]; for (var j = 0; j < nc.length; j++) { this.oc(nc[j], w); } for (var j = 1; j <= 50; j++) { this.oc('prop' + j, w); this.oc('eVar' + j, w); this.oc('hier' + j, w); }};mboxScPluginFetcher.prototype.oc = function(g, w) { var h = this.kc[g]; if (typeof(h) === 'undefined' || h === null || h === '') { return; } w.addParameter(g, h);};mboxScPluginFetcher.prototype.cancel = function() { };mboxStandardScPluginFetcher = function(b, kc) { mboxScPluginFetcher.call(this, b, kc);};mboxStandardScPluginFetcher.prototype = new mboxScPluginFetcher;mboxStandardScPluginFetcher.prototype.getType = function() { return 'standard';};mboxStandardScPluginFetcher.prototype.fetch = function(w) { w.setServerType(this.getType()); var e = this.lc(w); document.write('<' + 'scr' + 'ipt src="' + e + '" language="JavaScript"><' + '\/scr' + 'ipt>');};mboxAjaxScPluginFetcher = function(b, kc) { mboxScPluginFetcher.call(this, b, kc);};mboxAjaxScPluginFetcher.prototype = new mboxScPluginFetcher;mboxAjaxScPluginFetcher.prototype.fetch = function(w) { w.setServerType(this.getType()); var e = this.lc(w); this.x = document.createElement('script'); this.x.src = e; document.body.appendChild(this.x);};mboxAjaxScPluginFetcher.prototype.getType = function() { return 'ajax';};function mboxLoadSCPlugin(kc) { if (!kc) { return null; } kc.m_tt = function(kc) { var pc = kc.m_i('tt'); pc.G = true; pc.b = 'honda'; pc['_t'] = function() { if (!this.isEnabled()) { return; } var Q = this.rc(); if (Q) { var Eb = mboxFactoryDefault.isDomLoaded() ? new mboxAjaxScPluginFetcher(this.b, this.s) : new mboxStandardScPluginFetcher(this.b, this.s); Q.setFetcher(Eb); Q.load(); } }; pc.isEnabled = function() { return this.G && mboxFactoryDefault.isEnabled(); }; pc.rc = function() { var T = this.sc(); var pb = document.createElement('DIV'); return mboxFactoryDefault.create(T, new Array(), pb); }; pc.sc = function() { var tc = this.s.events && this.s.events.indexOf('purchase') != -1; return 'SiteCatalyst: ' + (tc ? 'purchase' : 'event'); }; }; return kc.loadModule('tt');};

